Cristiano Coelho
Cristiano Coelho

Reputation: 1735

Bind model to view from controller with alloy appcelerator

EDIT: Heres the example: https://github.com/prakash-anubavam/alloypreloadedsqlitedb/tree/master/app And sumarizing, how does the view details.xml know which model is it taking the data from?


Coming from asp.net mvc, im having some issues understanding this MVC.

I can understand how to use tables and such on the view like:

<TableView id="table" dataCollection="fighters" onClick="showId" dataTransform="transformData">

And fetch the data in the controller, i know it will use the global (singleton) collection of fighters and that will bind the model to the view.

But i have come across an example (i cant really find now) where it had a View, with no table, just some labels and text='{variableName}', which i assume it gets from the model. However the controller, did not assign the model (coming from an args[0] because it was always called from another controller which had the actual table), but it never assigned the model instance to the view in any way... so the question is how did it work? Is alloy smart enough to detect the actual model instance and use it? How would i do it? Something like $model = ...; or $.details.model = ...; or something like that? How did the view know where to take '{variableName}' from if the model was never assigned with a table or something.

Upvotes: 2

Views: 5113

Answers (2)

Fernando Fabreti
Fernando Fabreti

Reputation: 4366

I've found Tony Lukasavage answer the cleaner aproach to bind a existing model to view: You can find it here Josiah Hester answer is based on it (yeah, beware it's kind of a hack).

Although, Fokke Zandbergen gave an alternative worth looking at, maybe less hackish, don't know.

Expanding Josiah answer, you could do as follows:

On Master view:

<Alloy>
    <Collection src="modelName" />
    <View id="topview" class="container">
        <TableView id="tblModels" dataCollection="modelName" dataTransform="transformModel">
                  <Require src="rowModel"/>
        </TableView>
    </View>
</Alloy>

Then, on master controller:

//retrieve the id of the model
var thisId = e.row.thisIndex; 
//pass special key $model
var detailController = Alloy.createController("detail", { "$model": Alloy.Collections.detail.get(thisId) });
detailController.getView().open(); 

Then, on detail view:

<Alloy>
    <View  class="container" >
        <Label text="{id}"/>
        <Label text="{fullName}"/>
    </View>
</Alloy>

On detail controller: do nothing special.

If you have a transform function on master controller, it returns a object and you can use its properties inside detail view like "{fullName}".

Upvotes: 1

Josiah Hester
Josiah Hester

Reputation: 6095

This is actually a carryover hack, that may not work in the future, according to this thread.

If you take a look at index.js in your example (the controller), the model is assigned by the onClick event of the TableView:

function showId(e) {
    if (e.row.model) {
        var detailObj=fighters.get(e.row.model);
        // Assigning to the $model actually sets this model as the one to bind too
        var win=Alloy.createController('detail',{"$model":detailObj});
        win.getView().open();
    }
}

This is a "specai" variable that is automagically assigned for databinding, and is how it works underneath the covers (or did work under the covers).

This is undocumented and NOT ideal or recommended.

Upvotes: 2

Related Questions