0

I am using knockout and i am quiet new to it , i have a certain condition in which i have to define some read only properties in my model .

and later on i want to check the status/state of property that the field is read-only or not .

I searched hours on Google but find no suitable solution . what i find is this fiddle .

var ViewModel = function() {
var self = this;
self.getDisabledState = ko.observable(null);
self.getreadonlyState = ko.observable(null);
self.enable = function() {
    if (self.getDisabledState()) self.getDisabledState(undefined);
    else self.getDisabledState('disabled');
}
self.readonly = function() {
    if (self.getreadonlyState()) self.getreadonlyState(undefined);
    else self.getreadonlyState('readonly');
  }
}

ko.applyBindings(new ViewModel());

So i wonder if anybody help me .

Thanks in advance .

Ancient
  • 3,007
  • 14
  • 55
  • 104

5 Answers5

8

Although Maurizio's answer is correct in that you should bind a boolean from the view model that disables the input, one potential problem with using the "enable" binding can be that Internet Explorer styles disabled inputs in its own way and does not allow you to change that style. This can lead to disabled inputs that are barely legible.

To remedy this, we've created a custom binding handler that sets the readonly flag instead, and adds a specific style. This disables the input and allows us to style it our way.

This is the CSS style we added:

input.disabled
{
    border: 1px solid #888; 
    color: #888; 
    height: 22px !important; 
    padding: 2px;
}

And this is the custom binding handler, held in a common js file:

ko.bindingHandlers.readonly = {
    update: function (element, valueAccessor) {
        if (valueAccessor()) {
            $(element).attr("readonly", "readonly");
            $(element).addClass("disabled");
        } else {
            $(element).removeAttr("readonly");
            $(element).removeClass("disabled");
        }
    }
};

Then it's just a matter of applying the binding in the HTML, like this:

<input type="text" data-bind="value: MyValue, readonly: MyBoolean" />
Matt Winward
  • 1,255
  • 2
  • 15
  • 43
  • I seem to have had to call unwrapObservable on valueAccessor() to get this working. – Mike Gasparelli Oct 29 '15 at 01:45
  • 1
    This may be down to what you're actually binding to, or how you've set up the binding in the view. It sounds like you're somehow binding to an observable property, not its value. – Matt Winward Oct 29 '15 at 09:42
5

A little extender i just wrote

http://jsfiddle.net/cpsct/

ko.extenders.readonly = function(target, readonly) {
    var computed = ko.computed({
        read: target,
        write: function(value) {
            if(!computed.canWrite())
                throw "Observable in read only mode"

            target(value);
        }
    });

    computed.canWrite = ko.observable(!readonly);
    return computed;
};

update: If its a guard pattern you're after I can recommend looking into my lib Knockout.BindingConventions

Example http://jsfiddle.net/QzZPg/2/ (Write disable in the textbox)

Anders
  • 17,306
  • 10
  • 76
  • 144
  • can help me a bit further , i tried to write in second textbox , it not readonly . I can write in it . – Ancient Aug 12 '13 at 09:29
  • It sounded that you wanted a observable (property) that was readonly, the marked answer wont prevent the viewmodel or other code to update the value only the view – Anders Aug 12 '13 at 10:33
3

You can use this binginHandlers :

ko.bindingHandlers.readOnly = {
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        if (value) {
            element.setAttribute("disabled", true);

        } else {
            element.removeAttribute("disabled");
        }
    }
};

In my html :

<input type="text" id="create-finess" class="form-control" data-bind="readOnly: _locked" />

Finaly in my JS :

//Constructor of my view model

  function ViewModel(resx) {
       this._locked = ko.observable();
}

  // on init of the page i lock the input
 this._load = function () {
  this._locked(true);
}
Yvan
  • 1,081
  • 2
  • 20
  • 27
1
    html code:
  <input type="text" data-bind="value:SkuAttributeValue1,readOnly: IsAudit" class="form-control" />
 knockoutjs code:
    function ProductSkuItemModel(item) {
var self = this;
self.SkuAttributeValue1 = ko.observable(item.SkuAttributeValue1);
self.SkuAttributeValue2 = ko.observable(item.SkuAttributeValue2);
self.ProductSkuId = ko.observable(item.ProductSkuId);
self.SkuAttributeValue =ko.observable(skuAttributeName1 + ":" +      item.SkuAttributeValue1 + " " + skuAttributeName2 + ":" + item.SkuAttributeValue2);
self.IsAudit = ko.observable(false);
        }
   ko.bindingHandlers.readOnly = {
            update: function(element, valueAccessor) {
                var value = ko.utils.unwrapObservable(valueAccessor());
                //alert(value);

                if (!value) {
                    element.setAttribute("readOnly", true);
                } else {
                    element.removeAttribute("readOnly");
                }
            }
        };
adu
  • 39
  • 3
-5

You can use the enable binding to set your element to disabled like in this example, it works well for form elements like input, select, and textarea.:

<p>
    <input type='checkbox' data-bind="checked: hasCellphone" />
    I have a cellphone
</p>
<p>
    Your cellphone number:
    <input type='text' data-bind="value: cellphoneNumber, enable: hasCellphone" />
</p>

<script type="text/javascript">
    var viewModel = {
    hasCellphone : ko.observable(false),
    cellphoneNumber: ""
};
</script>

Knockout documentation: http://knockoutjs.com/documentation/enable-binding.html

Later if you want to check the status of your element just read the value of the hasCellphone() observable.

Maurizio In denmark
  • 4,226
  • 2
  • 30
  • 64
  • Thanks, this solution can work and i think we should always try to prefer recomended way . Thanks again – Ancient Aug 12 '13 at 10:07
  • 3
    He asked for a readonly property, this only disables the input. – Anders Aug 12 '13 at 10:50
  • The problem with disabling the input instead is that IE has a specific way of styling disabled inputs that can not be override. Readonly inputs, however, can be styled, which makes it more desirable. – Matt Winward Aug 07 '14 at 10:27
  • 1
    Readonly also continues to submit the value to the server which is desirable in some cases. – The Muffin Man Oct 15 '15 at 18:39