How do i pass a received array into underscore template

我与影子孤独终老i 提交于 2019-12-11 08:02:01

问题


I am getting a long array from PHP containing various data objects.

[{"commid":"1","uid":"0","pid":"3","comment":"comm","parid":null,"date":"2016-10-27 15:03:10"},
{"commid":"2","uid":"0","pid":"10","comment":"Ana","parid":null,"date":"2016-10-27 15:03:51"},
{"commid":"3","uid":"0","pid":"5","comment":"asss!","parid":null,"date":"2016-10-27 15:05:50"},
{"commid":"4","uid":"0","pid":"10","comment":"Lawl?","parid":null,"date":"2016-10-27 17:03:59"},
{"commid":"5","uid":"0","pid":"14","comment":"sd","parid":null,"date":"2016-11-06 00:25:04"},
{"commid":"6","uid":"0","pid":"14","comment":"sds","parid":null,"date":"2016-11-06 00:25:50"},
{"commid":"7","uid":"0","pid":"14","comment":"WOW!","parid":null,"date":"2016-11-08 15:06:18"},
{"commid":"8","uid":"0","pid":"13","comment":"Hello!?","parid":null,"date":"2016-11-08 15:14:30"}] 

My Backbone View which will be rendering the data is

var WorkPage = Backbone.View.extend({
    el: $('#indexcontent'),
    render: function() {
        Backbone.history.navigate('work');
        var _this = this;

        this.$el.html(workHTML);
        $.ajax({
            type: "GET",
            url: "includes/server_api.php/work",
            data: '',
            cache: false,
            success: function(html) {
                console.log(html);
                var compiledTemplate = _.template($('#content-box').html(), html);
                _this.$el.html(compiledTemplate);
            },
            error: function(e) {
                console.log(e);
            }
        });
        return false;
    }
});

My workHTML which will be rendered by Underscore is

<script type="text/template" id="content-box">
<div class="workhead">
    <h3 class="msg comment"><%= comment%></h3>
    <p class="date"><%= date%></p>
</div>
</script>
<div id="content-box-output"></div>

How do I implement a underscore loop here?


回答1:


You should take advantage of Backbone's features. And to do that, you need to understand how to use a REST API with Backbone.

Backbone's Model is made to manage a single object and handle the communication with the API (GET, POST, PATCH, PUT requests).

Backbone's Collection role is to handle an array of model, it handles fetching it (GET request that should return a JSON array of objects) and it also parse each object into a Backbone Model by default.

Instead of hard-coding a jQuery ajax call, use a Backbone collection.

var WorkCollection = Backbone.Collection.extend({
    url: "includes/server_api.php/work",
});

Then, modularize your views. Make an item view for each object of the array you received.

var WorkItem = Backbone.View.extend({
    // only compile the template once
    template: _.template($('#content-box').html()),
    render: function() {

        // this is how you pass data to the template
        this.$el.html(this.template(this.model.toJSON()));

        return this; // always return this in the render function
    }
});

Then your list view looks like this:

var WorkPage = Backbone.View.extend({
    initialize: function(options) {
        this.itemViews = [];
        this.collection = new WorkCollection();

        this.listenTo(this.collection, 'reset', this.render);

        // this will make a GET request to
        // includes/server_api.php/work
        // expecting a JSON encoded array of objects
        this.collection.fetch({ reset: true });
    },
    render: function() {
        this.$el.empty();
        this.removeItems();
        this.collection.each(this.renderItem, this);
        return this;
    },

    renderItem: function(model) {
        var view = new WorkItem({
            model: model
        });
        this.itemViews.push(view);
        this.$el.append(view.render().el);
    },
    // cleanup to avoid memory leaks
    removeItems: function() {
        _.invoke(this.itemViews, 'remove');
        this.itemViews = [];
    }

});

It's unusual to set the url in the render function, you should keep the responsibilities scoped to the right place.

The router could be something like:

var Router = Backbone.Router.extend({
    routes: {
        'work': 'workPage'
    },

    workPage: function() {
        var page = new WorkPage({
            el: $('#indexcontent'),
        });
    }
});

Then, if you want to see the work page:

var myRouter = new Router();

Backbone.history.start();

myRouter.navigate('#work', { trigger: true });

Templates and RequireJS

My index.html page contains this indexcontent div but the content-box which contains the template format which we are compiling is stored in different work.html. So, if i dont load this work.html in my main index.html i am unable to access content-box.

I would recommend to use the text require.js plugin and load each template for the view like this:

The work-item.js file:

define([
    'underscore', 'backbone',
    'text!templates/work-item.html',
], function(_, Backbone, WorkItemTemplate) {
    var WorkItem = Backbone.View.extend({
        template: _.template(WorkItemTemplate),
        /* ...snip... */
    });
    return WorkItem;
});

The work-page.js file:

define([
    'underscore', 'backbone',
    'text!templates/work-page.html',
], function(_, Backbone, WorkPageTemplate) {
    var WorkPage = Backbone.View.extend({
        template: _.template(WorkPageTemplate),
    });
    return WorkPage;
});



回答2:


In your index.html file you need to have _.each() method to iterate throught each element

<% _.each(obj, function(elem){ %>
<div class="workhead">
    <h3 class="msg comment"><%= elem.comment %></h3>
    <p class="date"><%= elem.date%></p>
</div>
<% }) %>

I make variable of your response just to have data to work with. In your View you need to set point on template template: _.template($("#content-box").html()), and in render method just send data as object.

Here is working code : jsFiddle




回答3:


Here is one way to load the template for each value in the data array.

var WorkPage = Backbone.View.extend({
    el: $('#indexcontent'),
    render: function() {
        Backbone.history.navigate('work');
        var _this = this;

        this.$el.html(workHTML);
        $.ajax({
            type: "GET",
            url: "includes/server_api.php/work",
            data: '',
            cache: false,
            success: function(data) {
                console.log(data);
                var $div = $('<div></div>');
                _.each(data, function(val) {
                    $div.append(_.template($('#content-box').html(), val));
                });
                _this.$el.html($div.html());
            },
            error: function(e) {
                console.log(e);
            }
        });
        return false;
    }
});


来源:https://stackoverflow.com/questions/40488041/how-do-i-pass-a-received-array-into-underscore-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!