knockout.js - Showing and hiding items based on a parent's value -
example jsfiddle
i have array of questions in model, following attributes:
- id: simple enough, id of question
- text: again, text question
- parents: array of question ids question dependent on
- activators: array of strings when parent's answer 1 of these values - question shown
- answer: answer question
- visible: boolean dictating whether question should visible on form
i'm using ko.mapping
bind json string (of i'm retrieving asmx web method) view model.
i have bunch of primary questions have no parents
or activators
these should visible, bunch of dependent questions depend on respective parent(s) having value before dependent visible. can extend far depdendents being dependent on dependents (if see mean).
my initial thought (as i'm getting there knockout.js) subscribe answer
property of question
, grab sub-set of questions depend on 1 answered. have @ value, compare them activators , show / hide necessary.
viewmodel.questions().foreach(function (question) { question.answer.subscribe(function (value) { var dependents = viewmodel.questions().filter(function (q) { return q.parents() && q.parents().indexof(question.id()) !== -1; }); dependents.foreach(function (d) { if (d.activators() && d.activators().indexof(value) !== -1) { d.visible(true); } else { d.visible(false); d.answer(null); } }); }); });
while works, can't feeling i'm missing trick here. have use ko.mapping
bind model view model it's been created me in asmx method, have extend view model (as i'm doing here cycling through questions
, subscribing each one.
maybe should using ko.computed
visible property, or maybe should creating kind of custom ko.bindinghandlers
instead? i'm not sure. correct way of trying achieve want?
there several ways of achieving you're after, 1 of them using custom bindings mentioned.
whether or not that's considered "knockout-correct" way, won't say, it's different approach , might give ideas @ least. here's 1 way of creating binding handler:
ko.bindinghandlers.hideifirrelevant = { update: function(element, valueaccessor, allbindingsaccessor, viewmodel, bindingcontext) { var question = ko.unwrap(valueaccessor()); if(!question.parents()) { $(element).show() // show question if has no parents return false; } var allquestions = bindingcontext.$root.questions(); var parents = allquestions.filter(function (q) { return question.parents().indexof(q.id()) !== -1; }); var shown = false; $.each(parents, function(i, parent) { if(parent.answer() && question.activators().indexof(parent.answer()) != -1) { shown = true; return false; } }); if(shown) { $(element).show(); } else { $(element).hide(); } } };
here's updated fiddle. note using custom binding, no longer need visible
property part of data model.
Comments
Post a Comment