Knerd
Knerd

Reputation: 2002

Binding DOM element property directly to other element

Is there a way to apply data bindings in javascript that are like WPF? Where you can bind directly to another element, without needing to build a viewmodel like in knockout?

To clarify what I wanna do, I want to hide a DOM element, based on the selected option in a select and that with just data-attributes and no need to write JavaScript code.

Upvotes: 1

Views: 109

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074295

You can use KO with arbitrary, non-observable data, but it will be a one-way binding that will not get updated if the data changes. Example:

var obj = {
  items: [
    "one",
    "two",
    "three"
  ]
};
ko.applyBindings(obj, document.body);
setTimeout(function() {
  obj.items.push("four"); // Doesn't appear when this runs
}, 1000);
<div data-bind="foreach: items">
  <div data-bind="text: $data"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

The reason is simple: KO has no way of knowing the value changed, which is the point of observables.

For when you want that behavior, KO itself might be overkill, but when you have a mix of wanting that and the full-blown KO behavior, Ryan N's interpolate plugin might be useful.

KO isn't the only game in town. RivetsJS, for instance, uses ES5's ability for properties to have getters and setters and dynamically rewrites your object to add them (converting a simple foo property into a foo property with a getter and setter). (I'm not suggesting using it, and I haven't used it in a real project, just pointing out that there are alternatives.) AngularJS, of course, uses a check-for-changes model instead, but is also dramatically more of an investment than a simple lib like KO or RivetsJS.

Looks good, what I need is, to hide and show a DOM element based on the choosen element in a select. I already thought about building something myself but that might be over the top.

That would be a use case for KO itself:

ko.applyBindings({
  selectValue: ko.observable("1")
}, document.body);
<select data-bind="value: selectValue">
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
  <option value="4">Four</option>
  <option value="5">Five</option>
</select>
<span data-bind="visible: +selectValue() % 2 == 1">Odd</span>
<span data-bind="visible: +selectValue() % 2 == 0">Even</span>
value
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

Now, I would normally avoid putting tha tcomputation in the data-bind (I'd use a computed), but I wanted to demonstrate being minimal in the model.

Upvotes: 2

Related Questions