Quiero lograr una oferta de clase dinámica, que debería asignar y reasignar la clase correcta en función de la variable, colocada en este campo. El problema que tuve, cuando induje la función setRed() , y luego setWhite() , ambas clases de color están vinculadas y, por supuesto, se considera la primera clase de CSS.
Tengo un elemento cuyo enlace se ve así:
<div data-bind='dxNumberBox: dxCustomCalc'></div> Hasta ahora hice elementAttr class ko.observable();
self.dxCustomCalc = { displayExpr: 'Name', keyExpr: 'Id', value: self.customCalc, //onValueChanged: function (e) { // self.childFormName(e.component.option('selectedItem')); //}, disabled: ko.computed(function () { return self.readOnly; }), elementAttr: { /* class: "is-valid-nok"*/ /* - red*/ /*class: "is-valid-onlyok" */ /* -white */ /*class: "is-required-empty",*/ /* - yellow */ class: ko.observable(), } };Y pasó por el elemento:
function setRed() { self.dxCustomCalc.elementAttr.class("is-valid-nok"); console.log("color changed to red") } function setWhite(){ self.dxCustomCalc.elementAttr.class("is-valid-onlyok"); console.log("color changed to white") } Las funciones se ejecutan en función del valor del campo. Por ejemplo, si el valor coincide, se activa la función setRed() . Luego, si el valor cambia y se cumple la condición, se activa la función setWhite() . El resultado que obtuve, después de ejecutar ambas funciones en la suscripción al elemento es:
<div data-bind="dxNumberBox: dxCustomCalc" class="dx-numberbox is-valid-nok is-valid-onlyok">El resultado que quiero lograr, después de ejecutar ambas funciones es:
<div data-bind="dxNumberBox: dxCustomCalc" class="dx-numberbox is-valid-onlyok">Usaría el enlace de class para establecer una clase CSS basada en un observable.
Podrías usarlo directamente
<div data-bind="dxNumberBox: dxCustomCalc, class: dxCustomCalc.cssClass"> o puede aplicar el enlace de class como parte de su enlace personalizado dxCustomCalc , usando ko.applyBindingsToNode() :
ko.bindingHandlers.dxNumberBox = { init: function(elem, valueAccessor, allBindings, viewModel) { const value = ko.unwrap(valueAccessor()); ko.applyBindingsToNode(elem, {class: value.cssClass}, viewModel); } }; function DxNumberBox() { this.dxCustomCalc = { cssClass: ko.observable("is-required-empty") }; this.setRed = () => this.dxCustomCalc.cssClass("is-valid-nok"); this.setWhite = () => this.dxCustomCalc.cssClass("is-valid-onlyok"); this.setEmpty = () => this.dxCustomCalc.cssClass("is-required-empty"); } const vm = new DxNumberBox(); ko.applyBindings(vm); .is-valid-nok { background-color: red; } .is-valid-onlyok { background-color: white; } .is-required-empty { border: 1px solid red; } <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.1/knockout-latest.js"></script> <button data-bind="click: setRed">Red</button> <button data-bind="click: setWhite">White</button> <button data-bind="click: setEmpty">Empty</button> <div data-bind="dxNumberBox: dxCustomCalc"> Profit Information </div> <hr> <pre data-bind="text: ko.toJSON($root, null, 2)"></pre>Las funciones se ejecutan en función del valor del campo.
Tener métodos adicionales como .setRed() es torpe e innecesario. Convierta cssClass en un observable calculado que calcula un nombre de clase en función del estado del modelo de vista, por ejemplo
cssClass: ko.pureComputed(() => { var value = self.value().trim(); if (value == '') return 'is-required-empty'; if (value < 0) return 'is-valid-nok'; return 'is-valid-onlyok'; });