Backbone.js from Beginner to ... (Part5)

Xây dựng website quản lý sản phẩm

Trong những part trước, Các kiến thức cơ bản để làm việc với Backbone đã được giới thiệu qua. Tôi tin chắc giờ là lúc bắt đầu cho một example đơn giản nào đó.

Trong part này , tôi đã tạo ra một website cơ bản , sử dụng backbone. Trong ví dụ này, website chỉ bao gồm chức năng list thông tin cơ bản của một sản phẩm.

Getting started

Việc đầu tiên là dựng lên một project với các folder của nó . Và sau đó chúng ta có thể bắt đầu với việc tạo ra một file với nội dung như sau:

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Product Management</title>
        <link rel="stylesheet" href="css/style.css" />
    </head>
    <body id="home">
        <table class="table">
            <thead>
            <tr>
              <th>Product Name</th>
              <th>Branch Name</th>
              <th>Price</th>
            </tr>
            </thead>
            <tbody id="products">
            </tbody>
        </table>
        <script src="js/jquery-1.7.1.min.js"></script>
        <script src="js/Underscore-min.js"></script>
        <script src="js/Backbone-min.js"></script>
        <script src="js/app.js"></script>
    </body>
</html>

Lưu thành file index.html và đặt ở root folder. Backbone là một mandatory mà yêu cầu bắt buộc phải có underscore.js . Tất nhiên chúng ta không thể thiếu được jQuery. Vì vậy việc link đến 2 thư viện này trước Backbone là điều bắt buộc.

Bây giờ sau khi đã có trang index.html , tất cả các code chúng ta sẽ có dưới đây sẽ được viết trong app.js . và bất kỳ style nào sẽ được viết trong file style.css

Tiếp theo bạn có thể tạo ra một dữ liệu giả như sau :

function ($) {

    var products = [
        { name: "Product 1", description: "1, a street, a town, a city, AB12 3CD", price: "100.000" },
        { name: "Product 2", description: "1, a street, a town, a city, AB12 3CD", price: "200.00" },
        { name: "Product 3", description: "1, a street, a town, a city, AB12 3CD", price: "5000" },
        { name: "Product 4", description: "1, a street, a town, a city, AB12 3CD", price: "200" },
        { name: "Product 5", description: "1, a street, a town, a city, AB12 3CD", price: "30.000" },
        { name: "Product 6", description: "1, a street, a town, a city, AB12 3CD", price: "15.000" },
        { name: "Product 7", description: "1, a street, a town, a city, AB12 3CD", price: "40.000" },
        { name: "Product 8", description: "1, a street, a town, a city, AB12 3CD", price: "30.000" },
        { name: "a", description: "1, a street, a town, a city, AB12 3CD", price: "30.000" }
    ];

} (jQuery));

Lưu đoạn code này ở trong file app.js. đoạn code này sẽ được import ngay sau khi load trang. Mỗi một item sẽ lưu trữ thông tin của từng product. Mặc dù việc lưu trữ dữ liệu thường được lưu tại server và sẽ có sự trao đổi qua lại giữa server và client. Tuy nhiên ở bài này tôi chỉ dừng lại ở việc lưu trữ dữ liệu trên clent. Sẽ có một bài viết khác để thực hiện việc tương tác với server.

Models

Model đại diện cho data của application. Trong ví dụ này một model sẽ là một sản phẩm cụ thể. Model sẽ có các thuộc tính như tên, mô tả, giá .... Như các bài trước đã hướng dẫn tạo một Model trong Backbone. :

var Product = Backbone.Model.extend({
    defaults: {
        name: "--"
    }
})

đoạn code trên nhằm tạo một model Product bằng việc sử dụng hàm extend. Thuộc tính Default sẽ cho phép thêm một dữ liệu mặc định của một model . Trong trường hợp này. Chúng ta sẽ add một giá trị "--" cho thuộc tính name. nếu trong dữ liệu không có name, default giá trị sẽ là "--".

Collections

Một collection là một class , nó thể hiện cho một group các model. ở đây chúng ta sẽ tạo ra một collection "wine" để lưu trữ các sản phẩm của chúng ta. Xem ví dụ dưới đây:

var Wine = Backbone.Collection.extend({
        model: Product
    })

Giống như một model, một collection của Backbone là một class có thể tùy chỉnh được . Một collections cũng có hàm extend và cho phép chúng ta thay đổi các thuộc tính của nó. và nó sẽ được xây dựng dựa trên một model nào đó. ở đoạn code trên, chúng là dùng model Product để xây dựng lên Collection Wine.

View

để hiện thị được dữ liệu lên view . Chúng ta cần phải truyền dữ liệu từ model , collection đến view và sẽ được hiện thị ra ngoài HTML page. Chúng ta sẽ sử dụng một vài view ở trong ứng dụng của chúng ta. Ta sẽ add trực tiếp code ngay sau collection Wine.

var ProductView = Backbone.View.extend({
        tagName: "tr",
        className: "product-container",
        template: $("#productTemplate").html(),

        render: function() {
            var that = this;
            // Compile the external template file using underscore
            $.get('templates/products/list2.html', function (data) {
                template = _.template(data, that.model.toJSON());
                that.$el.html(template);
            }, 'html');

            return this;
        }
    });

đoạn view này sẽ cho phép hiển thị toàn bộ dữ liệu từ model sang view. Giống như model và collection cũng được tạo ra bằng cách sử dụng extend ( như đã nói từ trước ). Backbone cung cấp một vài option cho việc hiển thị ra ngoài view như : className, tagName . tagName là thuộc tính để xác định bao ngoài của từng product là thẻ gì , và className thì xác định class được add vào tagName là gì. ở đây, tôi đã tạo sẵn một template "list2.html" nằm quyết đinh cho việc binding data tới view sẽ hiển thị ra sao.

Nói về hàm "render" . Trong hàm này, chúng ta có sử dụng đến hàm template() của Underscore. và truyền vào template mà chúng ta đã tạo ra. Khi truyền một argument thì Underscore sẽ không thực thi nó ngay lập tức mà sẽ trả về một method mà từ đó chúng ta có thể truyền data vào. Tuy nhiên khi đặt 2 arguments như đoạn code trên nó sẽ trả về một dữ liệu dạng html.

Template

Như đã nói ở những part trước, Underscore xây dựng micro-template và cung cấp template() để hỗ trợ cho việc tạo vòng lặp dữ liệu. để tạo trang HTML chúng ta nên tạo những template mà chúng ta sẽ sử dụng.

<td><%= name %></td>
<td><%= description %></td>
<td><%= price %></td>

Hoặc chúng ta có thể dụng <script> để tạo ra một template

<script id="nameTemplate" type="text/template">
    <td><%= name %></td>
    <td><%= description %></td>
    <td><%= price %></td>
</script>

và thêm vào trực tiếp file html mà chúng ta định sử dụng.

điều quan trọng khi add type cho script nhằm mục đích ngăn chặn thực thi sourcecode ngay khi chúng ta add vào. Trong template sử dụng cấu trúc HTML đặc biệt để xác định nơi nào thích hợp cho dữ liệu nào.

View chính

để kết thúc part này , chúng ta sẽ tạo ra một view cho Collection để hiện thị những collection này . Chúng ta đã thực sự tạo ra một view cho product. Tuy nhiên chưa view nào để hiện thị những view của product lên màn hình :

var WineView = Backbone.View.extend({
        el: $("#home"),

        initialize: function () {
            this.collection = new Wine(products);
            this.on("change:filterType", this.filterByType, this);
            this.collection.on("reset", this.render, this);
            this.render();
        },

        render: function () {

            var that = this;
            that.$el.find("#products").html("")
            _.each(this.collection.models, function (item) {
                that.renderProduct(item);
            }, this);
        },

    });

Trong view này sẽ attach những product view tới page của chúng ta. Như bạn biết. Một table đã được add vào index lúc đầu.

Ngay khi khởi tạo, chúng ta sẽ gọi đến hàm render của chính nó và nó sẽ render ra view của collection Wine. Chúng ta định nghĩa render method là method chính . Bên trong đây, chúng ta sẽ refer đến những view cần thiết như là Product view mà chúng ta đã tạo từ trước và tất nhiên việc sử dụng each() của Underscore nhằm duyệt qua dữ liệu model của Wine collection. Trong hàm each chúng ta có 2 argument : 1 là dữ liệu của collection này, hai là một function để chúng ta tương tác với từng dữ liệu. Tất cả những gì chúng ta cần làm với hàm callback là thực hiện việc render ra view của từng item collection.

điều cuối cùng chúng ta cần làm là tạo ra một hàm renderProduct. Trong đây chúng ta tạo ra một thể hiện của ProductView và ngay sau đó hãy đặt view này vào vị trí mà bạn mong muốn.

...
renderProduct: function (item) {

            var productView = new ProductView({
                model: item
            });

            this.$el.find("#products").append(productView.render().el);
        }

Ok. vậy là chúng ta đã có đủ nguồn tư liệu để có thể tạo ra một website liệt kê dữ liệu của product đã có. Tất cả những gì chúng ta cần làm là khởi tạo một view của collection

var wine = new WineView();

Ok . Hãy xem kết quả của bạn nhé!

Come and enjoy it!