Lấy dữ liệu và tạo/thêm/xoá/sửa nội dung Drupal bằng Angularjs thông qua Restws

26.042 views

Drupal, theo như các bạn đã biết Drupal là một CMS Framework rất flexible, ngoài ứng dụng CMS, Drupal còn có thể được dùng làm RESTful API với đầy đủ các chức năng, bài viết này mình hướng dẫn các bạn dùng Drupal kết hợp module Restws, Services để xây dựng RESTful API. Ở Client, mình sử dụng Angularjs để tương tác với Drupal thông qua RESTful API

Các bước chuẩn bị:
1.  Đối với site Drupal
  • Download và cài đặt module Restws, Services, Rest_service (module con của Services)
  • Cài đặt plugin Poster cho trình duyệt FireFox – Tool này dùng để test việc lấy dữ liệu thông qua Restws
2. Đối với Client
  • Tạo thư mục blog, trong thư mục tạo file blog.html dùng để hiển thị dữ liệu được lấy từ Drupal.
Các bước thực hiện
  • Đối với site Drupal
  1. Việc đầu tiên sau khi cài đặt phải đọc file README.txt của module Restws để xem URL path tương tác với Drupal.
  •  Ví dụ: file Json trả về nội dung của node như sau: http://example.com/node/1.json
  •  Xem chi tiết file README.txt ở http://cgit.drupalcode.org/restws/plain/README.txt?id=HEAD

     2. Vào Admin->Structure->Services, tạo endpoint với thông tin như sau

Screen Shot 2014-09-18 at 5.57.25 AM

     3. Click qua Server tab, chọn các thông tin sau

service config

 

     4. Click tạo Resource, click chọn thông tin CRUD Node (trong ví dụ này, mình chỉ tương tác với content của Drupal)

Screen Shot 2014-09-18 at 6.00.57 AM

Bây giờ, ta test thử xem cấu hình Restws có hoạt động không? Bằng cách sau khi cài đạt add on Poster ở firebox, ở đây ta sẽ test 2 trường hợp

  •  Lấy 1 content được chỉ định trực tiếp . Ví dụ: node/1
  •  Tạo node thông qua tool Poster.

       1. Mở Firefox -> Tool->Poster -> Nhập các thông tin sau

Screen Shot 2014-09-20 at 9.40.36 PM

    2. Click Get, sẽ thấy thông tin file XML được hiển thị.

Screen Shot 2014-09-20 at 9.41.42 PM

Như vậy, bước đầu đã thành công khi lấy dữ liệu thông qua module Restws bằng addon của Firefox.

Đối với Client

Tạo file blog.html lấy tất cả dữ liệu content của Drupal với node type là angular

 <head>
        <title> Blog List via Angular</title>
        <script src="js/jquery-1.7.2.js"></script>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
        <script type="text/javascript" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
        <script src="js/angular.min.js"></script>
        <script src="blog.js" type="text/javascript"></script>
        <script type="text/javascript" src="js/angular-resource.js"></script>
        <script type="text/javascript" src="js/angular-route.js"></script>

  </head>
<body id="content" ng-app="crudBlog" >
    <div ng-controller="PostsCtrl">
        <div class="container" ><a href="http://vietjs.com/wp-content/uploads/2014/09/Screen-Shot-2014-09-20-at-8.40.54-PM.png"><img src="http://vietjs.com/wp-content/uploads/2014/09/Screen-Shot-2014-09-20-at-8.40.54-PM.png" alt="Screen Shot 2014-09-20 at 8.40.54 PM" width="904" height="621" class="alignnone size-full wp-image-131" /></a>
            <div class="row">
                <div class="col-md-9">
                    <table class="table table-striped">
                        <thead>
                        <th>Title</th>
                        <th>Description</th>
                        </thead>
                        <tbody>
                            <tr ng-repeat="post in posts">
                                <td> <a href="#" title="{{post.title}}" ng-click="view(post.nid)" > {{post.title}} </a></td>
                                <td> {{post.body.value}} </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>

        </div>
    </div>
</div>
</body>

blog.js

var crudBlog = angular.module('crudBlog', ['ngResource']);
crudBlog.controller("PostsCtrl", ['$scope', '$http', 'NodeService', function($scope, $http, NodeService) {
        $http.get("http://27.3.156.40/restws/node.json?type=article")
                .success(function(data, status, headers, config) {
                    console.log(data);
                    $scope.posts = data.list;
                }).error(function(data, status, headers, config) {
            alert("No data");
        });

}]);

Refresh lại blog.html, ta sẽ có kết quả sau:
Screen Shot 2014-09-20 at 8.40.54 PM

Theo đoạn code trên, đã lấy được giá trị content có node type là angular từ site của Drupal. Bây giờ, bổ sung thêm ví dụ, thay đổi content từ client và cập nhật lại dữ liệu cho site Drupal.
Ở ví dụ này, ta thay đổi tiêu đề của 1 bài viết sau đây từ site Drupal (bài viết có nid: 2)
Screen Shot 2014-09-20 at 8.46.46 PM

Vào file blog.html, bổ sung vào phần hiển thị form để thay đổi content :

  <head>
        <title> Blog List via Angular</title>
        <script src="js/jquery-1.7.2.js"></script>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
        <script type="text/javascript" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
        <script src="js/angular.min.js"></script>
        <script src="blog.js" type="text/javascript"></script>
        <script type="text/javascript" src="js/angular-resource.js"></script>
        <script type="text/javascript" src="js/angular-route.js"></script>

    </head>
    <body id="content" ng-app="crudBlog" >
        <div ng-controller="PostsCtrl">
            <div class="container" >
                <form name="editNode">
                    <div class="title">
                        <label>Title</label>
                        <div class="text">
                            <input size="30" type="text" name ="title" ng-model="newnode.title">
                        </div>
                    </div>
                    <div class="body">
                        <label>Body</label>
                        <div class="content">
                            <textarea name="body" ng-model="newnode.body"  ng-maxlength="500" rows="10" cols="50" >Body</textarea>
                        </div>
                    </div>
                    <input type="hidden" name="nid" ng-model="newnode.nid" />
                    <input type="button" value="Save" ng-click="edit()" />
                </form>
                <div class="row">
                    <div class="col-md-9">
                        <table class="table table-striped">
                            <thead>
                            <th>Title</th>
                            <th>Description</th>
                            </thead>
                            <tbody>
                                <tr ng-repeat="post in posts">
                                    <td> <a href="#" title="{{post.title}}" ng-click="view(post.nid)" > {{post.title}} </a></td>
                                    <td> {{post.body.value}} </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

            </div>
        </div>
    </body>

Cập nhật lại file blog.js, thêm phần xử lý hiển thị content và cập nhật lại giá trị cho server:


varcrudBlog = angular.module('crudBlog', ['ngResource']);
crudBlog.service('NodeService', ['$http', function($http) {
        this.get = function(data) {
            var newnode = {
                title: data.title,
                body: data.body.value,
                nid: data.nid,
            };
            return newnode;
        }

        this.save = function(data) {
            var id = data.id;
            return $http({
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                method: "PUT",
                url: "http://27.3.156.40/restws/rest/node/" + id + ".json",
                data: "title=" + data.title + "&body[und][0][value]=" + data.body,
            }).success(function(data) {
                alert("Content has been updated successfully")
            }).error(function(data) {
                alert("Can not uptdated node!Opps");
            });
        }
    }]);

crudBlog.controller("PostsCtrl", ['$scope', '$http', 'NodeService', function($scope, $http, NodeService) {
        $http.get("http://27.3.156.40/restws/node.json?type=article")
                .success(function(data, status, headers, config) {
                    $scope.posts = data.list;
                }).error(function(data, status, headers, config) {
            alert("No data");
        });
        $scope.view = function(id) {
            $http.get("http://27.3.156.40/restws/rest/node/" + id + ".json").
                    success(function(data, status, headers, config) {
                        //console.log(data.body.value);
                        $scope.newnode = angular.copy(NodeService.get(data));
                    })
        };
        $scope.edit = function() {
            var node = {
                title: $scope.newnode.title,
                body: $scope.newnode.body,
                id: $scope.newnode.nid,
            };
            NodeService.save(node);
        }
    }]);

Screen Shot 2014-09-20 at 8.56.18 PM

 

Click vào title của bất kỳ content nào bạn muốn thay đổi. Ở ví dụ này, ta muốn thay đổi content có title
Bene Facilisis Neque

Screen Shot 2014-09-20 at 9.00.09 PM

 

Thay đổi title của content với nội dung: Update Content via Angular.js

Screen Shot 2014-09-20 at 9.32.24 PM

Vào site Drupal kiểm tra nội dung đã được cập nhật chưa (ở ví dụ trên ta cập nhật node 2)
Screen Shot 2014-09-20 at 9.36.25 PM

Woa, cập nhật thành công rồi ^^.

Như vậy, mình đã trình bày phần cấu hình và cách lấy dữ liệu, cập nhật dữ liệu từ một client khác. Phần còn lại xoá và tạo khi nào rảnh mình update nữa nhé :p.

Comments

  1. Ví dụ khi xài thẻ: {{post.body.value}}. Giả sử đường truyền chậm, thì khi chưa binding lên, trang web vẫn còn hiển thị expression. Nếu dùng thẻ span: thì sẽ có những trường hợp đụng với css.
    Vậy làm cách nào để khắc phục trường hợp này?
    (Bên KnockoutJs cho phép binding trong comment html để hiển thị ra ngoài website.)
    Hỏi ngoài lề: Tại sao thông tin cá nhân đều bị viết hoa?

      1. Không phải khác phục. Lý do là Angular’s template sẽ không được render khi load chưa xong, nên trường hợp mã template kiểu <div>{{ post.body.value }}</div> sẽ không bị show ra và người dùng không thấy.
      2. Tên người dùng viết hoa do theme nó vậy :))
  2. À, để viết lại chỗ span, bị ẩn mất rồi:
    <span ng-bind-template="{{var1}} - {{var2}}"><span>

  3. Bài viết thiết thực.
    Chị Thảo nên dùng <td ng-bind-html="post.body.value"></td> để mã HTML được render đúng.

Leave a Reply

%d bloggers like this: