Home > other >  Knockout JS Add/Remove class
Knockout JS Add/Remove class

Time:04-22

I am using Knockout to generate a dynamic form:

function FormField(data) {
  var self = this;
  self.Name = ko.observable(data.Name);
  self.Type = ko.observable(data.Type);
  self.Options = ko.observableArray(data.Type !== 'text' ? data.Options : []);
  self.Default = ko.observable(data.Default);
  if (self.Type() === 'Yes/No') {
    this.Default.subscribe(function(newValue) {
      console.log(newValue);
    });
  }
}

function ViewModel(data) {
  var self = this;
  self.Fields = ko.observableArray(ko.utils.arrayMap(data, function(item) {
    return new FormField(item);
  }));
  self.HiddenElements = ko.observableArray([]);
  self.Default = ko.observable();
}

ko.applyBindings(new ViewModel([{ 
  Name: "Test",
  Type: "Yes/No",
  Options: [{ name: "Yes" }, {name: "No" }],
  Default: ""
}]));
input[type=radio] {
  display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.1/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div data-bind="foreach: Fields">
    <!--ko if: $parent.HiddenElements().indexOf(Name()) == -1 -->
    <div><b type="text" data-bind="text: Name"></b>:</div>
    <!--ko if: Type() == "Yes/No"-->
    <div data-bind="foreach: Options">
    <label data-bind="css:$data.name == 'Yes' ? 'btn btn-success fa fa-circle-o' : 'btn btn-danger fa fa-circle-o'">
    <input type="radio" value="cherry" data-bind="value: $data.name ,checked: $parent.Default" />
   <span data-bind="text: $data.name"></span></label>
    </div>
   <!--/ko-->
   <!--/ko-->
</div>

The output:
wrong output without selected button

I am trying to remove the class fa-circle-o and add class fa-check-circle-o when any of the buttons is checked.

Expected output:
output with 'Yes' selected

CodePudding user response:

The checked binding on the <input> essentially says:

When this option is checked, store $data.name in the $parent.Default observable

That means in your label, you can find out whether the label belongs to a checked input by doing:

$data.name === $parent.Default()

So your binding will be something like:

<label 
  
  data-bind="css: {
    'btn-success': $data.name === 'Yes',
    'btn-danger': $data.name !== 'Yes',
    'fa-check-circle-o': $data.name === $parent.Default(),
    'fa-circle-o': $data.name !== $parent.Default()
  }">...</label>

  • Related