Search code examples
javascriptdom-eventsenyo

Enyo custom event is not handled and undefined in simple example


I'm learning the events in Enyo js framework and can't understand why I get the error and event onModelChanged is not handled. Error message is:

"Uncaught TypeError: undefined is not a function"

Code:

debugger; 
enyo.kind({
    name : "MyModel",
    kind: "enyo.Model",
    defaultSource: "mocked",
    published: {
        title : "not set",
        text : "not set",       
    },
    
    events : {
        onModelChanged : "",
    },
    
    handlers: {
        onModelChanged : "modelLoadedHandler" 
    },
    
    modelLoadedHandler : function(inSender, inEvent){
        debugger;
        console.log("handler in model");
        console.log(inEvent.textMsg);
        return true;
    },
        
    fetch : function(opts){
        this.inherited(arguments);
        debugger;
        this.doModelChanged({textMsg: "fire event"}); // Uncaught TypeError: undefined is not a function
            
    }       
        
});



var model = new MyModel();
model.fetch();

P.S. Leave this code as an answer not to be deleted by jsfiddle

enyo.kind({
    name: "MyMockSource",
    kind: "enyo.Source",
    fetch: function(model, opts) {
        if(model instanceof enyo.Model) {
            opts.success({title: "testing", text: "Some stuff"});
        } else {
            throw new Error("Model mock only");
        }
    }
});

new MyMockSource({name: "mocked"});

enyo.kind({
    name : "MyModel",
    kind: "enyo.Model",
    source: "mocked",
    attributes: {
        title : "not set",
        text : "not set",       
    },
    fetched: function(opts){
        this.inherited(arguments);
        enyo.log("fetched");
        // Do something here if you need to, otherwise you might want to overload
        // the parse method and set parse: true to modify the retrieved data
    },
    titleChanged: function(was, is) {
        enyo.log("Title is now: " + is);
    }
});

enyo.kind({
    name: "MyView",
    components: [
        {kind: "Button", content: "Fetch", ontap: "fetch"},
        {name: "title"},
        {name: "text"}
    ],
    bindings: [
        {from: "model.title", to: "$.title.content"},
        {from: "model.text", to: "$.text.content"}
    ],
    fetch: function() {
        this.set("model", new MyModel());    // Probably want to create model elsewhere
        this.model.on("change", enyo.bindSafely(this, "modelChanged"));
        this.model.fetch();
    },
    modelChanged: function() {
        this.log("Something happened to my model!");
    }
});

new enyo.Application({ name: "app", view: "MyView" });

Solution

  • enyo.Model is not an enyo.Object (much less an enyo.Component). It does not support published properties or events. You want to define attributes for a model. You can still get notifications on property changes using the propertyChanged event or by using observers.

    Also, you probably want to overload fetched if you want to know that fetching has completed. fetch possibly returns before the data has been fetched.

    If you want to subscribe to events from outside then you probably want to bind to a specific property on the model or to the changed event using model.on('change') (note this is a different event system from the events: [] system used elsewhere.

    Update: Here's a fiddle showing the various ways to work with the model and binding to data

    http://jsfiddle.net/RoySutton/5jo0p7ar/