1
votes

this is my backbone code ,where iam using a underscore template,it is working fine now i am trying to make that template external and load from there

this is my sample backbone code

Backbone Application

<div class="list"></div>

<script id="personTemplate" type="text/template">
    <strong><%= name %></strong> (<%= age %>) - <%= occupation %>
</script>
<script type="text/javascript">
var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
        age: 23,
        occupation: 'worker'
    }
});

var PersonView = Backbone.View.extend({
   tagName: 'li',

    template: _.template( $('#personTemplate').html()),

    initialize: function(){
        this.render();
    },

    render: function(){
        this.$el.html( this.template(this.model.toJSON()));
    }
});
var person = new Person;  // a person object created...
//person.set('name', 'abhi');
var personView = new PersonView({ model: person });
personView.el   // ---->; You can call this method and it will display the view..
$(document.body).html(personView.el);
</script>
</body>
</html> 

what is really need is that i will place this template <strong><%= name %></strong> (<%= age %>) - <%= occupation %> in a external file. i dont know much about its extension,i think it can be a html file and load the template from there ,i researched about it and find some sample code and tried some thing like this

<script type="text/javascript">
_.mixin({templateFromUrl: function (url, data, settings) {
    var templateHtml = "";
    this.cache = this.cache || {};

    if (this.cache[url]) {
        templateHtml = this.cache[url];
        alert(templateHtml);
    } else {
        $.ajax({
            url: url,
            method: "GET",
            async: false,
            success: function(data) {
                templateHtml = data;
                alert(templateHtml);
            }
        });

        this.cache[url] = templateHtml;
    }

    return _.template(templateHtml, data, settings);
}});
var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
        age: 23,
        occupation: 'worker'
    }
});

var PersonView = Backbone.View.extend({
   tagName: 'li',

   template:_.templateFromUrl("templatefile1.html", {"name": "value","age":10}) ,
   // template:_.templateFromUrl("templatefile1.html", this.model.toJSON()) ,
  //template: _.template( $('#personTemplate').html()),
    initialize: function(){
        this.render();
    },

    render: function(){
    alert(this.template);
        this.$el.html( this.template);
    }
});
var person = new Person;  // a person object created...
//person.set('name', 'abhi');
var personView = new PersonView({ model: person });
personView.el   // ---->; You can call this method and it will display the view..
$(document.body).html(personView.el);
</script>

but when i am calling teemplate like this template:_.templateFromUrl("templatefile1.html", {"name": "value","age":10}) , it is working but when i trying to pass the pass model to that template like this

template:_.templateFromUrl("templatefile1.html", this.model.toJSON())

i am getting exception like

Uncaught TypeError: Cannot read property 'toJSON' of undefined 

how can i resolve this issue

2
Careful with $(document.body).html(personView.el);, looks like you're storing <script>s inside your <body> and $('body').html(...) clears <body> before adding the new stuff.mu is too short
@ mu is too short 1 thanks for your thoughts,it is just a sample codeabhi
@ mu is too short i have tried that but nor working can you please provide the code?abhi
What specifically have you tried? What specifically went wrong?mu is too short

2 Answers

1
votes

You're saying something like this:

var PersonView = Backbone.View.extend({
    //...
    template: _.templateFromUrl("templatefile1.html", this.model.toJSON()),
    //...
});

What do you think this is in that context? It certainly won't be an instance of your view since no instances have been made yet. this is going to be window at the level and window won't have a useful model property. You need to defer that call until you have an instance of your view created with a model property.

You could make template a method:

template: function() {
    return _.templateFromUrl('templatefile1.html', this.model.toJSON());
}

and then call it at the appropriate time:

render: function(){
    this.$el.html(this.template());
    return this; // <----- Standard practise so you can x.append(v.render().el)
}

I'd recommend against using async:false with $.ajax though, that's a nasty thing to do to people. Instead, you should hand templateFromUrl a callback function that it can call when the template has come in from the server.

If you're going to be doing this sort of thing a lot then you could add a template function to a base view:

var BaseView = Backbone.View.extend({
    template: function() {
        // This assumes that you have exactly one of `this.model` and
        // `this.collection`, you can do other things here if that doesn't
        // work in your world.
        var data_source = this.model || this.collection;
        return _.templateFromUrl(this.template_name, data_source.toJSON());
    }
});

and then use it your PersonView:

var PersonView = BaseView.extend({
    template_name: 'templatefile1.html',
    render: function() {
        this.$el.html(this.template());
        return this;
    },
    //...
});
0
votes

You need to make the model reusable, and define a url:

 var PersonModel = Backbone.Model.extend({
    defaults: {
        name: 'Untitled',
        age: 0,
        occupation: null,
    },
    url: "/somefile.json"
});

Create a listener for model changes inside the view, and fetch the model:

    initialize: function(options){
        this.listenTo(this.model, "change", this.render);
        this.model.fetch();
    }

Create a new model, then pass it to a new view:

var person = new PersonModel();
var personView = new PersonView({ model: person });