Problem getting dynamically added data custom attribute

98 views
Skip to first unread message

Todd Geissinger

unread,
Sep 30, 2015, 2:06:16 PM9/30/15
to KnockoutJS
I have the following mapping:

<input type="text" style="border: none; text-align: right; max-width: 75px;" data-bind="percent: { decimalPlaces: 2 }, attr: { 'data-value': DefaultMarkup }" />

I have the following bindingHandler:

ko.bindingHandlers.percent = {
    update: function (element, valueAccessor) {
        ko.bindingHandlers.value.update(element, valueAccessor);
        console.log('Element: ', element);
        console.log('dataset:', element.dataset)
        console.log('bind:', element.dataset.bind);
        console.log('value:', element.dataset.value);
    },
};

The logging in the console is as follows:

Element:  <input type="text" style="border:​ none;​ text-align:​ right;​ max-width:​ 75px;​" data-bind="percent:​ { decimalPlaces:​ 2 }​, attr:​ { 'data-value':​ DefaultMarkup }​" data-value="-0.1">
dataset: DOMStringMapbind: "percent: { decimalPlaces: 2 }, attr: { 'data-value': DefaultMarkup }"value: "-0.1"__proto__: DOMStringMap
bind: percent: { decimalPlaces: 2 }, attr: { 'data-value': DefaultMarkup }
value: undefined

jQuery Element:  x.fn.x.init[1]0: 
                    attributes:
                        name: "data-value"
                        nodeValue: "-0.1"

jQuery data: Objectbind: "percent: { decimalPlaces: 2 }, attr: { 'data-value': DefaultMarkup }"__proto__: Object

What I am trying to get is the data-value.

It is showing with both Javascript as well as jQuery when I log element to the console..  When I go to access data-value then I get undefined.

I created a separate page with just:

<input type="text" style="border:​ none;​ text-align:​ right;​ max-width:​ 75px;​" data-bind="percent:​ { decimalPlaces:​ 2 }​, attr:​ { 'data-value':​ DefaultMarkup }​" data-value="-0.1">

and I was able to access the data-value custom attribute.

Any one have any ideas how I can get the data-value from the element that is passed in?


Thanks,

Todd Geissinger

Gunnar Liljas

unread,
Sep 30, 2015, 2:46:34 PM9/30/15
to knock...@googlegroups.com
Why do you need a data-value? 

The value you send along to value.update now is hardly what you want in the value.

Shouldn't it be

<input type="text" style="border:​ none;​ text-align:​ right;​ max-width:​ 75px;​" data-bind="value: DefaultMarkup, percent:​ { decimalPlaces:​ 2 }>



--
You received this message because you are subscribed to the Google Groups "KnockoutJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to knockoutjs+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Todd Geissinger

unread,
Sep 30, 2015, 3:06:54 PM9/30/15
to KnockoutJS
I am using it as a original value.  The user want to be able to display a formatted value when the input does not have focus and wants the edited non formatted one when editing.  It is a part of the requirement to have this functionality.

I didn't post the whole bindingHandlers.percent method as to cut down on the post size.

The main reason for doing it this way is because when the page is first rendered it only displays the plain text and not the formatted one.

I am new to knockout and may not be doing it the best method but trying to work my thru.

I need the input boxes to display and restrict when using numbers, currency as well as percents.  I also need it to limit to the number of decimal points.

Below is the full percent bindinghandler.

    ko.bindingHandlers.percent = {
        init: function (element, valueAccessor) {
            var decimalPlaces = valueAccessor().decimalPlaces;
            setTimeout(function () { element.focus(); element.blur(); }, 100);

            $(element).on("keydown", function (event) {
                // Allow: backspace, delete, tab, escape, and enter
                if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
                    // Allow: Ctrl+A
                    (event.keyCode == 65 && event.ctrlKey === true) ||

                    // Allow: . ,
                    //(event.keyCode == 188 || event.keyCode == 190 || event.keyCode == 110) ||
                    //(event.keyCode == 190 || event.keyCode == 110) ||

                    // Allow: home, end, left, right
                    (event.keyCode >= 35 && event.keyCode <= 39)) {
                    // let it happen, don't do anything
                    return;
                }
                    // Allow: . if it is not in current value
                else if (event.keyCode == 190 || event.keyCode == 110) {
                    if (decimalPlaces == 0) {
                        event.preventDefault();
                    }
                    else if (element.value.indexOf('.') == -1) {
                        return;
                    }
                    else {
                        event.preventDefault();
                    }
                }
                else {
                    var length = element.value.length;
                    var lastIndexOf = element.value.lastIndexOf('.');
                    var selectionStart = element.selectionStart;

                    // Ensure that it is a number and stop the keypress
                    if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) {
                        event.preventDefault();
                    }
                        // Prevent if there are 2 decimal places already if typing after the decimal point
                    else if (length > 0 && lastIndexOf > -1 && length == lastIndexOf + 1 + decimalPlaces && selectionStart > lastIndexOf) {
                        event.preventDefault();
                    }
                }
            });
            // TODO:  Still needs more work - getting close ?
            $(element).on("focus", function (event) {
                if (this.hasAttribute('data-value')) {
                    this.value = this.getAttribute('data-value');
                }
            });
            $(element).on("blur", function (event) {
                this.setAttribute('data-value', this.value);
                this.value = this.value + '%';
            });
        },
        update: function (element, valueAccessor) {
            ko.bindingHandlers.value.update(element, valueAccessor);

            element.value = formatPercent(.7, 2);

            var item = $(element).hide().fadeIn('fast');

            console.log(item.data());

            //console.log(item);
            $('#troubleshooting').text(item);

            //console.log('Element: ', element);
            //console.log('dataset:', element.dataset)
            //console.log('bind:', element.dataset.bind);
            //console.log('value:', element.dataset.value);

            //console.log('jQuery Element: ', $(element));
            //console.log('jQuery data:', $(element).data())
            //console.log('bind:', element.dataset.bind);
            //console.log('value:', element.dataset.value);


            //element.value = element.getAttribute('data-value');
            //console.log($(element).data());

            //console.log(element);
            //console.log(element.dataset)
            //console.log(element.dataset.bind);
            //console.log(element.dataset.value);

            // <input type="text" style="border: none; text-align: right; max-width: 75px;" data-bind="percent: { decimalPlaces: 2 }, attr: { 'data-value': DefaultMarkup }" data-value="0.1">
            //$('#troubleshooting').text('');
        },
    };
 
Thanks,

Todd Geissinger

Todd Geissinger

unread,
Sep 30, 2015, 10:06:56 PM9/30/15
to KnockoutJS
By taking a break and looking at the knockout site I was able to see one way to do it and get it to work.

I changed the binding as follows:

<input type="text" style="border: none; text-align: right; max-width: 75px;" data-bind="percent: DefaultMarkup, decimalPlaces: 2, attr: { 'data-value': DefaultMarkup }" />

Then I changed to the update to the following:

        update: function (element, valueAccessor, allBindingsAccessor) {
            ko.bindingHandlers.value.update(element, valueAccessor);

            var value = ko.utils.unwrapObservable(valueAccessor());
            var decimalPlaces = allBindingsAccessor().decimalPlaces;

            element.value = formatPercent(value, decimalPlaces); 
        },

I was able to get the initial value to display as a percent.

Thanks,

Todd Geissinger
Reply all
Reply to author
Forward
0 new messages