3

I have a complex form with many selects whose state (enabled/disabled) depends on the value of some other controls, so it could happen that these selects are disabled when submitting the form (and the select value is not posted). I need to post the selected value even in the case the user is not allowed to change the select.

I saw some solutions here HTML form readonly SELECT tag/input (mainly the solution is to have an hidden field synchronized with the disabled select).

I am thinking to taking a slightly different approach: I want to use knockout (already used in the project) to display the select only when the data is editable, and display a readonly input (or a div/span) otherwise.

How can I use knockout to simplify this approach?

Community
  • 1
  • 1
Daniele Armanasco
  • 7,289
  • 9
  • 43
  • 55

3 Answers3

3

Simply disabling the select is enough to prevent it from posting -- you don't have to make it readonly. This is actually pretty straight-forward. With the attr binding, you can apply an attribute conditionally. So all you need is an observable that holds a boolean state for the select:

In your view model

self.DisableSelects = ko.observable(false);

Your select binding

attr: { disabled: DisableSelects }

Then, you just set the observable to true when you want any selects bound like that to be disabled:

viewModel.DisableSelects(true)

Obviously, if you want greater granularity, you just create more observables like this and bind appropriately.

EDIT

Your question is not explicit about what you're actually wanting, but I have a feeling that the problem is you actually do want the value posted even if it's disabled. On that, I have to agree with the first answer on the linked question: don't rely on the posted value being there at all. Making a field readonly or disabled does not prevent the value from being changed. Every modern browser has development tools built-in that let's you change HTML in place (i.e. remove the readonly or disabled flag), and anyone with even a basic knowledge of HTML can pull that off. IF you want a field readonly, then the only safe way to accomplish that is to completely disregard the posted value. You can do all sorts of tricks with hidden inputs and such, but that can easily be gotten around as well.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • Yes, I do want the value posted even if it's disabled. I'm sorry that I wasn't not so explicit and will edit the question. I have no security concerns because my application is a data-centric intranet application, but I will pay more attention to the issues that you have highligthed. Thank you! – Daniele Armanasco Apr 20 '13 at 16:22
  • Well, even though security may not be a concern, it's always better to treat any application as if it may be compromised, if for no other reason than if you *stop* worrying about it for one app, you might not remember to actually worry about it for the next app that *will* matter. – Chris Pratt Apr 22 '13 at 14:39
1

In my viewModel I define the property relative to the state of the select, the property bounded to the select value and a computed observable that "reads" the description of the selected option in the select:

AppViewModel: function () {
        var self = this;
        self.SelectVisible = ko.computed(function () {
            return true;  // return true or false depending on your context
        }, self);
        self.Category = ko.observable("");
        self.CategoryText = ko.computed(function () {
            return $("#Category option[value='" + self.Category() + "']").text();
        }, self);
        // other code ...
}

In the page I have a select always enabled and a readonly input whose visibility is mutually esclusive and depends on a viewModel property:

<select name="Category" id="Category" data-bind="value: Category, visible: SelectVisible">
   <option value="S">Standard</option>
   <option value="N">CatN</option>
   <option value="C">CatC</option>
</select>
<input style="display: none;" type="text" readonly="readonly" data-bind="value: CategoryText, visible: !SelectVisible()"/>
Daniele Armanasco
  • 7,289
  • 9
  • 43
  • 55
0

You could just bind the knockout view model variable "IsDisable" to the select list

SHIBIN
  • 397
  • 3
  • 5