Search code examples
javascriptbackbone.jstitaniumtitanium-alloy

Titanium Alloy Data Binding: How to get current model from clicked view?


I am new to Titanium Alloy, the MVC framework, and Backbone.js, so I'm having a little trouble wrapping my head around some of the concepts.

Similar questions have been asked previously:

Getting ID of clicked TableRow in Titanium Alloy?

Appcelerator Titanium Alloy: How to store data on a ScrollableView to use in click event

but, though I am trying to follow the answers, I just cannot seem to get the following code to work as expected.

Basically, when data binding in Titanium Alloy, how do you pass the current model to the controller?

(Also, this is my first question on here, so if there is any area in which I could improve my query please let me know, thanks).

Model

exports.definition = {
config: {
    columns: {
        "issueNo": "number",
        "date": "string",
        "summary": "string",
        "cover": "string"
    },
    adapter: {
        type: "sql",
        collection_name: "issue"
    }
},
extendModel: function(Model) {
    _.extend(Model.prototype, {
        // extended functions and properties go here
    });

    return Model;
},
extendCollection: function(Collection) {
    _.extend(Collection.prototype, {
        // extended functions and properties go here
    });

    return Collection;
}
};

View

<Alloy>
<Collection src="issue" />
<Window class="container" onClose="cleanup">
    <View id="header">
        <Label id="title">Christian</Label>
    </View>
    <View id="library" class="body" layout="vertical" dataCollection="issue">
        <View id="issuesList" model="{alloy_id}" onClick="alertModel">
            <ImageView id="cover" image="{cover}"></ImageView>
            <Label id="date" text="{date}"></Label>
            <Label id="summary" text="{summary}"></Label>
            <View class="border"></View>
        </View>
    </View>
    <View id="store" class="body" layout="vertical" visible="false" backgroundColor="yellow">

    </View>
    <View id="footer">
        <TabbedBar id="bottomNav" platform="ios" index="0" onClick="viewSelect">
            <Labels>
                <Label>Library</Label>
                <Label>Store</Label>
            </Labels>
        </TabbedBar>
    </View>
</Window>
</Alloy>

Controller

var Newsstand = require("ti.newsstand");
Newsstand.enableDevMode();

var issues = Alloy.Collections.issue;
issues.fetch();

var issue1 = Alloy.createModel("issue", {
    issueNo: 1,
    date: "1/1/2014",
    summary: "Some text.",
    cover: "/issues/cover_1.png"
});

var issue2 = Alloy.createModel("issue", {
    issueNo: 2,
    date: "1/2/2014",
    summary: "Some text.",
    cover: "/issues/cover_2.png"
});

var issue3 = Alloy.createModel("issue", {
    issueNo: 3,
    date: "1/3/2014",
    summary: "Some text.",
    cover: "/issues/cover_3.png"
});

issues.add(issue1);
issues.add(issue2);
issues.add(issue3);


function viewSelect(tabbedBar) {
    var index = tabbedBar.index,
        library = $.library,
        store = $.store,
        bottomNav = $.bottomNav;

    if (index === 0) {
        library.visible = true;
        store.visible = false;
    } else {
        store.visible = true;
        library.visible = false;
    }
}

function alertModel(e){
    var modelId = e.model,
        model = issues.get(modelId),
        issueNumber = model.get("issueNo");

    alert(issueNumber);
}

function cleanup() {
    $.destroy();
}

$.index.open();

Solution

  • Updated answer based on comment from OP:

    On the second link you posted, if binding data to Views it says you need to set touchEnabled="false" on all of the elements in the view template and then use e.source.model in your alertModel function. Tested and it works for me.

    var modelId = e.source.model,
            model = issues.get(modelId),
            issueNumber = model.get("issueNo");
    

    I always use ListViews to bind my data and you don't need to explicitly set touchEnabled when using those.

    Additionally, the alloy_id doesn't get created until you save a model to the DB. Calling .add() on your collection doesn't save it, you have to call .save() on your model to have it saved.

    Sample here: https://github.com/foolprooflabs/testforcurzmg