Results 1 to 8 of 8

Thread: ViewModel -> Model - How does one load the model?

  1. #1
    Sencha User
    Join Date
    Apr 2010
    Posts
    21

    Default ViewModel -> Model - How does one load the model?

    Hi there,

    I have a data editing screen which is created using a form. The form has a ViewModel and ViewController defined. The ViewModel is linked to a Model like so:

    Code:
    Ext.define("TemplateViewModel", {
        extend: "Ext.app.ViewModel"
        , alias: "viewmodel.TemplateViewModel" 
        , model: "TemplateModel"
    });
    The TemplateModel is defined as having a proxy:

    Code:
    , proxy: {
            type: 'rest'
            , url: "/p/"
            , reader: {
                type: 'json'
    }
    }
    So calling TemplateModel.load(id) works fine,

    The question I have is how do I trigger a load against my server in a way that loads the data into the ViewModel, so it's available to the View/UI form and with the 2-way data binding?

    Thanks!

  2. #2
    Sencha Premium User evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    19,255
    Answers
    759

    Default

    Currently you'll need a session attached to your view model. To load it:

    Code:
    {
        links: {
            theUser: {
                reference: 'User',
                id: 42
            }
        }
    }
    Twitter - @evantrimboli
    Former Sencha framework engineer, available for consulting.
    As of 2017-09-22 I am not employed by Sencha, all subsequent posts are my own and do not represent Sencha in any way.

  3. #3
    Sencha User
    Join Date
    Apr 2010
    Posts
    21

    Default

    Thanks for responding. I thought that sessions might be the answer, but of all the new Ext 5.0 features, sessions are the one area which will need significant TLC in regards to documentation. It is one of aspects of Ext 5.0 that have really stumped me (the other being that ViewModel data is inherited down the component tree).

    So, with sessions, if I follow the Kitchen Sink "Model Validation" example, I would add the following to my view:

    Code:
        , session: true
        , viewModel: {
            links: {
                template: {
                    reference: "TemplateModel"
                    , id: 43
                }
    
    
            }
        }
    But no matter how I try - whether I try and do the bind explicitly in initComponent(), or try and define the session as an Ext.data.session.Session object - I get failures in instantiation. With the example code above, the error is:

    [W] XTemplate evaluation exception: Cannot call method 'bind' of null ext-all-debug.js:5600

      • [COLOR=red !important]Ext.define.privates.sort[/COLOR]
    [/COLOR]

    and no server query is sent for the record.
    If, rather, I try the bind in initComponent, I get a second type of error:

    Code:
        , initComponent: function () {
            this.callParent(arguments);
            this.getViewModel().bind({
                reference: "TemplateModel"
                , id: this.PromoMaterialTemplateID
            },
            function (t) {
            });
        }
    The error is:


    and no server query is sent for the record.
    If I give it a new session, with the code:

    , initComponent: function () {
    this.callParent(arguments);
    this.getViewModel().setSession(Ext.create("Ext.data.session.Session"))
    this.getViewModel().bind({
    reference: "TemplateModel"
    , id: this.PromoMaterialTemplateID
    }, function (t) { });
    }

    I get the no errors/exceptions, and the server query is sent for the record (yay!), but the bindings I have in the form do not work (i.e. a bind: "{TemplateModel.Name}" doesn't show the name).

    So, I must be misunderstanding something fundamental in how this all should work -

    Firstly, maybe - what is the "reference" supposed to reference. It seems it's supposed to reference the model name (TemplateModel in my case), but it doesn't reference the namespace - so how does that work?

    In all the examples, such as yours and in the Kitchen Sink, it looks really easy - the viewModel is given a links list and that's all that's needed.

    When trying myself, it seems that to use:

    viewModel: {
    links: { ... }
    }

    I need to prep the session by pre-loading a store with the relevant record - is that the case?

    Thanks

  4. #4
    Sencha Premium User evant's Avatar
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    19,255
    Answers
    759

    Default

    Code:
    Ext.require('*');
    
    Ext.define('User', {
        extend: 'Ext.data.Model',
        fields: ['id', 'first', 'last'],
        proxy: {
            type: 'ajax',
            url: 'data.json'
        }
    })
    
    
    Ext.onReady(function() {
    
        var session = new Ext.data.session.Session();
    
        new Ext.panel.Panel({
            renderTo: Ext.getBody(),
            width: 200,
            height: 200,
            session: session,
            bind: {
                title: '{theUser.first}',
                html: '{theUser.last}'
            },
            viewModel: {
                links: {
                    theUser: {
                        reference: 'User',
                        id: 3
                    }
                }
            }
        });
    });
    Server:
    Code:
    {
        "id": 3,
        "first": "Foo",
        "last": "Barrington"
    }
    Twitter - @evantrimboli
    Former Sencha framework engineer, available for consulting.
    As of 2017-09-22 I am not employed by Sencha, all subsequent posts are my own and do not represent Sencha in any way.

  5. #5
    Sencha User
    Join Date
    Apr 2010
    Posts
    21

    Default

    Righto,

    Firstly, the 'reference' field in the viewModel -> links section is the class name, not the namespace name. That's important to recognize.

    So I put this example to the test, and it works. I then started replacing pieces with my own view and model, and source data. It ended up working.

    My application builds a complete application view by:
    1. First, building my "ApplicationView" (which is a border layout). This includes a viewModel. It then displays itself. At this point I have a GUI on the screen.
    2. Second, the code calls a router.
    3. The router creates a new view (the one I'm trying to get working), via Ext.create(). This is a Panel with a form layout, and has the viewModel defined with links, as described above.
    4. I add this to the pre-existing rendered view.
    The code to do this is as follows:

    Code:
            var c = Ext.getCmp (this.mainTargetDiv);
            if (!c) {
                return;
            }
            config = config || {};
            config.session = new Ext.data.session.Session();
            var v = Ext.create("TemplateView", config);
            c.removeAll();
            c.add (v);
    If I have, in my main ApplicationView, a viewModel defined as: {}, then I get the error:

    W] XTemplate evaluation exception: Cannot call method 'bind' of null ext-all-debug.js:5600

    • [COLOR=red !important][E] Ext.Component.applyBind(): Cannot use bind config without a viewModel ext-all-debug.js:5600
    [/COLOR]

    Object


    ext-all-debug.js:5606




    But, if I change my ApplicationView and remove the viewModel entirely, the component I create later and add to the ApplicationView's central area loads and works perfectly.

    Note that in my TemplateView i have my viewModel defined as : viewModel: { type: "MyVM" }.

    So it seems that my main view is, if a viewModel has been defined on it, triggering some code that clears my TemplateView viewModel when it is added to the panel for display.

    Is there something I can do to avoid causing this to happen? I.e. can I declare my view model(s) in some manner to avoid the problem?

  6. #6
    Sencha User
    Join Date
    Apr 2010
    Posts
    21

    Default

    Righto, so my problem is easy to reproduce, if you replace the Ext.onReady() from the prior example code with:


    Code:
    Ext.onReady(function() {
    
    
        var session = new Ext.data.session.Session();
    
    
        var p = new Ext.panel.Panel({
            renderTo: Ext.getBody(),
            layout: 'fit',
            width: 200,
            height: 200,
            viewModel: {},  // This is the important line
            title: 'outer'
        });
    
    
    
    
        var pp = new Ext.panel.Panel({
            session: session,
            bind: {
                title: '{theUser.first}',
                html: '{theUser.last}'
            },
            viewModel: {
                links: {
                    theUser: {
                        reference: 'User',
                        id: 3
                    }
                }
            }
        });
    
    
        p.add(pp);
    });
    If you comment out the line marked "this is important", it works, otherwise it fails.

    Also, note that it fails if you define both viewModels using viewModel: { type: ... }} in the component configuration.

  7. #7
    Sencha User nmorado's Avatar
    Join Date
    Mar 2009
    Location
    New Jersey, USA
    Posts
    63
    Answers
    1

    Default

    EventIn your code above why do one has to create session manually? Is that required? Wouldn't it be nice if component automatically creates this under the hood?Thanks

  8. #8
    Sencha User
    Join Date
    Apr 2010
    Posts
    21

    Default

    nmorado, it doesn't need to be created manually.

    Ideally what I'd probably do is have a session object shared between my list screen and detail screen, since I think that's the purposes. But for now I'm not trying to achieve that sort of clever functionality.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •