Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: this.adapter(...)[action] is not a function sightglass.js:159:8 #510

Closed
ORESoftware opened this issue Jul 22, 2015 · 11 comments
Closed

Comments

@ORESoftware
Copy link

I was following the directions that our supreme leader placed on JSFiddle prompted by a question on StackOverlow:

http://jsfiddle.net/eH4zG/252/

my code looks similar

but I get this

TypeError: this.adapter(...)[action] is not a function sightglass.js:159:8

my adapter is using the colon : like the example, but my only guess is that the adapter is not being picked up in my program? But it is being registered, I can verify that, so I can't explain this behavior.

@ORESoftware
Copy link
Author

I am not sure if it matters but here is my configuration

define(
    [
        'rivets'
    ],
    function (Rivets) {
        Rivets.configure({

            // Attribute prefix in templates
            prefix: 'rv',

            // Preload templates with initial data on bind
            preloadData: true,

            // Root sightglass interface for keypaths
            rootInterface: '.',

            // Template delimiters for text bindings
            //templateDelimiters: ['{', '}'],

            templateDelimiters: ['{*{', '}*}'],

            // Augment the event handler of the on-* binder
            handler: function (target, event, binding) {
                this.call(target, event, binding.view.models)
            }

        });
    }
);

@ORESoftware
Copy link
Author

I am not sure about binding.view.models, or what that's doing

@ORESoftware
Copy link
Author

as you can see in the image below, window.rivets.adapters[:] is defined, but given the error, I don't know which action function it's looking for. maybe you can simply improve the error message and let us know which action is missing in the adapter. thanks.

here is image:
screenshot 2015-07-22 16 42 39

@ORESoftware
Copy link
Author

I think I figured out the problem

here's a picture to help you help me, the image represents the adapter hash obj / associated array.
The first key/value is for '.', the second is for ':'

screenshot 2015-07-22 16 53 25

looks like the there was breaking changes - I need to implement observe and unobserve instead of subscribe and unsubscribe, etc? is that right?

as you can see from the image, my adapter[:] implements publish, read, subscribe,unsubscribe....

@ORESoftware
Copy link
Author

Seems to work now, I changed my adapter

from this

define(
    [
        'rivets',
        'backbone'
    ],

    function (Rivets, Backbone) {

        // Rivets.js Backbone adapter
        Rivets.adapters[':'] = {
            // set the listeners to update the corresponding DOM element
            subscribe: function (obj, keypath, callback) {
                if (obj instanceof Backbone.Collection) {
                    obj.on('add remove reset', callback);
                }
                else if (obj instanceof Backbone.Model) {
                    obj.on('change:' + keypath, callback);
                }
                else {
                    throw new Error('Rivets error: not backbone model or collection');
                }
            },
            // this will be triggered to unbind the Rivets.js events
            unsubscribe: function (obj, keypath, callback) {
                if (obj instanceof Backbone.Collection) {
                    obj.off('add remove reset', callback);
                }
                else if (obj instanceof Backbone.Model) {
                    obj.off('change:' + keypath, callback);
                }
                else {
                    throw new Error('Rivets error: not backbone model or collection');
                }
            },
            // define how Rivets.js should read the property from our objects
            read: function (obj, keypath) {
                // if we use a collection we will loop through its models otherwise we just get the model properties
                //TODO: @rhodee As of 0.3.2 there is a data-each-[item] binding to iterate over items in an array.
                if( obj instanceof Backbone.Collection){
                    return obj.models
                }
                else if(obj instanceof Backbone.Model){
                    return obj.get(keypath);
                }
                else{
                    throw new Error('Rivets error: not backbone model or collection');
                }
            },
            // It gets triggered whenever we want update a model using Rivets.js
            publish: function (obj, keypath, value) {
                obj.set(keypath, value);
            }
        };

    });

to this

define(
    [
        'rivets',
        'backbone'
    ],

    function (Rivets, Backbone) {

        // Rivets.js Backbone adapter
        Rivets.adapters[':'] = {
            // set the listeners to update the corresponding DOM element
            observe: function (obj, keypath, callback) {
                if (obj instanceof Backbone.Collection) {
                    obj.on('add remove reset', callback);
                }
                else if (obj instanceof Backbone.Model) {
                    obj.on('change:' + keypath, callback);
                }
                else {
                    throw new Error('Rivets error: not backbone model or collection');
                }
            },
            // this will be triggered to unbind the Rivets.js events
            unobserve: function (obj, keypath, callback) {
                if (obj instanceof Backbone.Collection) {
                    obj.off('add remove reset', callback);
                }
                else if (obj instanceof Backbone.Model) {
                    obj.off('change:' + keypath, callback);
                }
                else {
                    throw new Error('Rivets error: not backbone model or collection');
                }
            },
            // define how Rivets.js should read the property from our objects
            get: function (obj, keypath) {
                // if we use a collection we will loop through its models otherwise we just get the model properties
                //TODO: @rhodee As of 0.3.2 there is a data-each-[item] binding to iterate over items in an array.
                if( obj instanceof Backbone.Collection){
                    return obj.models
                }
                else if(obj instanceof Backbone.Model){
                    return obj.get(keypath);
                }
                else{
                    throw new Error('Rivets error: not backbone model or collection');
                }
            },
            // It gets triggered whenever we want update a model using Rivets.js
            set: function (obj, keypath, value) {
                obj.set(keypath, value);
            }
        };

    });

FML

can you prevent someone else from making the same mistake (following an old tutorial) that I made? perhaps you just missing one patch/ALIAS ?

@Duder-onomy
Copy link
Collaborator

If you read the most current docs on the website, they illustrate these issues. The adapter syntax changed in the latest major semvar.

I agree, A nice example of using rivets with backbone should be provided.

You will also need to listen for the backbone change event on the backbone collection.

Keep in mind, default backbone does not support nested properties. You cannot do something like, rv-value='model:object:somethingElse' because that will call your adapter for each time it accesses the observed from the keypath ':' , meaning that the second time is sees the ':' it will run your adapter again. Nor can you do rv-value='model:object.somethingElse'. Rivets will read this correctly the first time. But your model will get out of sync because you need to teach backbone how to handle nested properties.
In Practice, when using this where I work, will implement some unknown keypath separator to trick rivets into giving you the entire keypath of the observed property. We use the -> when we access nested properties. Looks like rv-value='backboneModel:object->property' this will send the string 'object->property' to the ':' adapter which we then replace the arrow with the dot, and pass to an infinite nested backbone model. Here is our adapter

Here is an example of implementing infinate nesting with backbone models and collections. We use this with rivets all the time. Things like, rv-value='model:nestedModel->collection'

Let me know if this helps. As with most things backbone, getting things to work with it is not totally easy, but once you get it working how you want. It feels like you have a Lamborghini and there is no magic.

@ORESoftware
Copy link
Author

yeah, thanks, on the Rivets Guide page there is this as an example of two-way binding

rivets.binders.toggle = {
  bind: function(el) {
    adapter = this.config.adapters[this.key.interface]
    model = this.model
    keypath = this.keypath

    this.callback = function() {
      value = adapter.read(model, keypath)
      adapter.publish(model, keypath, !value)
    }

    $(el).on('click', this.callback)
  },

  unbind: function(el) {
    $(el).off('click', this.callback)
  },

  routine: function(el, value) {
    $(el)[value ? 'addClass' : 'removeClass']('enabled')
  }
}

it clearly is using the adapter.publish adapter.read functions, which are 'deprecated'

is this all being maintained? I know it's a lot of work

@Duder-onomy
Copy link
Collaborator

Right now the main man Mike is doing a rewrite. There are a few of us that are not official maintainers, but lurk super hard. Otherwise there are some random people here and there. As far as the word maintain... I am not sure there is actually anything "wrong" with it. There are many open issues but most are a muut point based on the authors implementation, or someones desire to se a binder make it into rivets core. There are many "nice to have" features. But the way rivets is made, you are supposed to implement custom binders, formatters and components to solve your problems.
The documentation is definitely a bummer, but straight up, the source code is very readable and I think you would learn more/faster by just looking at the source vs. looking at the docs. Just my opinion though.

There is this thread: #500

Please close the issue if your problem is solved.

@ORESoftware
Copy link
Author

word I appreciate it

@Duder-onomy
Copy link
Collaborator

Could you please close your ticket if your question is answered?

@ORESoftware
Copy link
Author

for sure

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants