Is there a way to bind dynamic list of properties?

54 views
Skip to first unread message

David Weng

unread,
Apr 23, 2017, 1:26:10 PM4/23/17
to KnockoutJS
I want to write some generic code for a search form. The list of search fields can be changed. So instead of hard-code search fields like

  self.keywords = ko.observable();
  self.age = ko.observable();

   ...

    <input type="text" placeholder="Keywords" value="" data-bind="value: keywords">

I want to do something like 

   self.clientSearchFields=[new searchField{'name':'keywords', 'type':'textmatch'}, new searchField{...} ]

   self.clientSearchData =  ko.observable();


   <input type="text" placeholder="Keywords" value="" data-bind="value: clientSearchData().keywords">

 and when any search field changes, it can trigger the filter function like

   self.filteredRecords = ko.computed(function() {
     return ko.utils.arrayFilter(self.items, function(r) {
            ko.utils.arrayForEach(self.clientSearchFields(), function(item) {
              if(self.clientSearchData() && self.clientSearchData()[item.name] && self.clientSearchData()[item.name].length>0){
                 .....
              }
            });
            .....
        });


  basically, I don't want to hardcode any search field name in the ViewModel.    

  Is there a way?

  Thanks


noirabys

unread,
Apr 24, 2017, 7:06:03 AM4/24/17
to KnockoutJS
hi,

wrap the fields into a observableArray:

function searchField(data){
  var self = this;
  self.type = data.textmatch;
}

 self.clientSearchFields=ko.observableArray([new searchField({'name':'keywords', 'type':'textmatch'}), new searchField({...})... ]);

add a read call to "keywords" property to your computed ( that will add the dependency )

the computed will automatically reavaluated on adding a searchfield, or changing of the keywords property

best regards,
 noirabys

yx weng

unread,
Apr 25, 2017, 4:28:54 PM4/25/17
to KnockoutJS
Thanks.

But how do I reference those fields by key, I need reference them with something like

self.clientSearchFields[0] or self.clientSearchFields['keywords']

not something like

self.clientSearchFields.keywords

since the field names are not static.

I think I need reference them in computed field, and also need reference them in search html like input 

Gunnar Liljas

unread,
Apr 25, 2017, 4:49:14 PM4/25/17
to knock...@googlegroups.com
You certainly can, by traversing the array, but I wonder why you need to access them directly..

yx weng

unread,
Apr 25, 2017, 4:59:41 PM4/25/17
to KnockoutJS
Ok, I didn't explain it clearly.

So I have a list of search fields, if I need display keywords search box on one place, and age search box on another.  What data-bind I can use?

If the field is static, I can add something like 

<input class="form_field_input" type="text" placeholder="Keywords" value="" data-bind="value: filter_keywords ">

but since the fields are dynamic, I would like to add like

<input class="form_field_input" type="text" placeholder="Keywords" value="" data-bind="value: filters['keywords'] ">

If I can do like that, how do I put it in computed so changes can be pick

   self.filter=ko.computed(function(){
     var v='';
     for(var searchField in searchFields){  //  'keywords' in one item in searchFields
       v += filters[searchField.name];   
     }
    ....

I tested with code like that, but seems the changes didn't trigger the computed.
Reply all
Reply to author
Forward
0 new messages