简体   繁体   中英

rivets.js trying to get custom adapter to work

I am trying to get a custom adapter to work with rivets.js, but it neither changes the model nor does it ever call the routine. If there's someone out there who is also using rivets.js, I could use some help with this one:

JsFiddle Example Code

 var menuContext = { menu: { watchList: { status: false, view: function() { // call other view } }, profile: { status: false, view: function() { // call other view } } } }; rivets.binders['on-select-item'] = { bind: function(el) { var adapter = rivets.adapters[rivets.rootInterface]; var model = this.model; var keypath = this.keypath; var that = this; this.callback = function(ev) { ev.preventDefault(); var value = adapter.get(model, keypath); var newValue = !value; adapter.set(model, keypath, newValue); }; el.addEventListener('click', this.callback); }, unbind: function(el, value) { el.removeEventListener('click', this.callback); }, routine: function(el, value) { console.log('I am only being called once!'); value ? el.classList.add('enabled') : el.classList.remove('enabled'); } }; var menu = document.querySelector("#menu"); rivets.bind(menu, menuContext); 
 #menu .enabled { background-color: green; } 
 <script src="https://rawgit.com/mikeric/rivets/master/dist/rivets.bundled.min.js"></script> <ul id="menu"> <li> <a href="#" role="button" rv-on-select-item="menu.watchList.status"> Item 1, value should toggle (true|false) <span rv-html="menu.watchList.status"></span> </a> </li> <li> <a href="#" role="button" rv-on-select-item="menu.profile.status"> Item 2, value value should toggle (true|false) <span rv-html="menu.profile.status"></span> </a> </li> </ul> 

The keypath here is the full path string you specify in your template, but your model here is the object holding the last property in keypath ( don't ask me why, that's how it's when debugging ) and looking at the source code of default adapter , it doesn't seem to be doing any traversal:

get: function(obj, keypath) {
  return obj[keypath];
},
set: function(obj, keypath, value) {
  return obj[keypath] = value;
}

So you'll have to resolve the keypath by yourself. Something like the following will do in this case:

 var menuContext = { menu: { watchList: { status: false, view: function() { // call other view } }, profile: { status: false, view: function() { // call other view } } } }; rivets.binders['on-select-item'] = { bind: function(el) { var adapter = rivets.adapters[rivets.rootInterface]; var model = this.model; var keypath = this.keypath; var that = this; this.callback = function(ev) { ev.preventDefault(); var key = keypath.split('.').slice(-1); var value = adapter.get(model, key); var newValue = !value; adapter.set(model, key, newValue); }; el.addEventListener('click', this.callback); }, unbind: function(el, value) { el.removeEventListener('click', this.callback); }, routine: function(el, value) { console.log('I am only being called once!'); value ? el.classList.add('enabled') : el.classList.remove('enabled'); } }; var menu = document.querySelector("#menu"); rivets.bind(menu, menuContext); 
 #menu .enabled { background-color: green; } 
 <script src="https://rawgit.com/mikeric/rivets/master/dist/rivets.bundled.min.js"></script> <ul id="menu"> <li> <a href="#" role="button" rv-on-select-item="menu.watchList.status"> Item 1, value should toggle (true|false) <span rv-html="menu.watchList.status"></span> </a> </li> <li> <a href="#" role="button" rv-on-select-item="menu.profile.status"> Item 2, value value should toggle (true|false) <span rv-html="menu.profile.status"></span> </a> </li> </ul> 

I know you're following the two way binding example at official site, but the library seem to have got major updates since. If you want to know "why" better place would be the github repo where the author could give some insights.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM