Pregunta

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?

¿Fue útil?

Solución 2

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()"/>

Otros consejos

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.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top