2015-01-30 18 views
14

Tôi có một dịch vụ AngularJS mà giao tiếp với máy chủ và trả về bản dịch của các phần khác nhau của ứng dụng:AngularJS ui-router: cách giải quyết dữ liệu điển hình trên toàn cầu cho tất cả các tuyến đường?

angular 
    .module('utils') 
    .service('Translations', ['$q','$http',function($q, $http) { 
     translationsService = { 
      get: function(section) { 
       if (!promise) { 
        var q = $q.defer(); 
        promise = $http 
          .get(
           '/api/translations', 
           { 
            section: section 
           }) 
          .success(function(data,status,headers,config) { 
           q.resolve(result.data); 
          }) 
          .error(function(data,status,headers,config){ 
           q.reject(status); 
          }); 
        return q.promise; 
       } 
      } 
     }; 

     return translationsService; 
    }]); 

Tên của phần này được chuyển như section tham số của get chức năng.

Tôi đang sử dụng mô-đun AngularJS ui-router và sau mẫu thiết kế được mô tả here

Vì vậy, tôi đã tình trạng sau config:

angular.module('app') 
    .config(['$stateProvider', function($stateProvider) { 
    $stateProvider 
    .state('users', { 
     url: '/users', 
     resolve: { 
      translations: ['Translations', 
       function(Translations) { 
        return Translations.get('users'); 
       } 
      ]    
     }, 
     templateUrl: '/app/users/list.html', 
     controller: 'usersController', 
     controllerAs: 'vm' 
    }) 
    .state('shifts', { 
     url: '/shifts', 
     resolve: { 
      translations: ['Translations', 
       function(Translations) { 
        return Translations.get('shifts'); 
       } 
      ]    
     }, 
     templateUrl: '/app/shifts/list.html', 
     controller: 'shiftsController', 
     controllerAs: 'vm' 
    }) 

này hoạt động tốt nhưng khi bạn có thể nhận thấy tôi phải rõ ràng chỉ định translations trong thông số giải quyết. Tôi nghĩ rằng đó là không đủ tốt vì điều này trùng lặp logic.

Có cách nào để giải quyết các bản dịch trên toàn cầu và tránh các bản sao mã không. Ý tôi là một số loại phần mềm trung gian.

Tôi đã suy nghĩ về việc lắng nghe cho các $stateChangeStart, sau đó nhận được bản dịch cụ thể cho nhà nước mới và ràng buộc chúng với bộ điều khiển, nhưng tôi đã không tìm thấy cách để làm điều đó.

Mọi lời khuyên sẽ được đánh giá rất cao.

Lưu ý quan trọng: Trong trường hợp của tôi, số translations object được giải quyết phải chứa dữ liệu bản dịch, không phải dịch vụ/nhà máy/bất cứ điều gì.

Trân trọng.

+0

Tôi không có thời gian để viết câu trả lời, nhưng tôi nên đề cập rằng định nghĩa trạng thái là các đối tượng javascript đơn giản. Bạn có thể đặt chúng trong một danh sách (đặt khai báo 'name:' ​​như là một thuộc tính lồng nhau của mỗi trạng thái) và lặp lại trên mỗi danh sách. Trên mỗi trạng thái bạn lặp lại, hãy thêm giải pháp. –

Trả lời

6

Mặc dù đây là một câu hỏi rất cũ, tôi muốn đăng giải pháp mà tôi đang sử dụng ngay bây giờ. Hy vọng nó sẽ giúp ai đó trong tương lai. Sau khi sử dụng một số phương pháp khác nhau, tôi đã đưa ra một số beautiful angularjs pattern by John Papa

Ông đề xuất sử dụng dịch vụ đặc biệt routerHelperProvider và định cấu hình các trạng thái làm đối tượng JS thông thường. Tôi sẽ không sao chép toàn bộ nhà cung cấp ở đây. Xem liên kết ở trên để biết chi tiết. Nhưng tôi sẽ chỉ cho tôi cách giải quyết vấn đề của mình bằng các phương tiện của dịch vụ đó.

Dưới đây là phần mã của nhà cung cấp mà trong đó có đối tượng JS và biến đổi nó để cấu hình trạng thái:

function configureStates(states, otherwisePath) { 
    states.forEach(function(state) { 
     $stateProvider.state(state.state, state.config); 
}); 

tôi chuyển nó như sau:

function configureStates(states, otherwisePath) { 

    states.forEach(function(state) { 

     var resolveAlways = { 

      translations: ['Translations', function(Translations) { 

       if (state.translationCategory) { 

        return Translations.get(state.translationCategory); 

       } else { 

        return {}; 

       } 

      }], 

     }; 



     state.config.resolve = 

      angular.extend(state.config.resolve || {}, resolveAlways || {}); 



     $stateProvider.state(state.state, state.config); 

    }); 

}); 

Và cấu hình tuyến đường của tôi đối tượng bây giờ trông như sau:

 { 
      state: ‘users’, 
      translationsCategory: ‘users’, 
      config: { 
       controller: ‘usersController’ 
       controllerAs: ‘vm’, 
       url: ‘/users’. 
       templateUrl: ‘users.html' 
      } 

vì vậy, những gì tôi đã làm:

Tôi đã triển khai đối tượng resolveAlways có thuộc tính tùy chỉnh translationsCategory, tiêm dịch vụ Translations và giải quyết dữ liệu cần thiết. Bây giờ không cần phải làm điều đó mọi lúc.

25

Hãy để tôi chỉ cho bạn cách tiếp cận của tôi. Có is a working plunker

Hãy có một translation.json như thế này:

{ 
    "home" : "trans for home", 
    "parent" : "trans for parent", 
    "parent.child" : "trans for child" 
} 

Bây giờ, chúng ta hãy giới thiệu tình trạng siêu mẹroot

$stateProvider 
    .state('root', { 
    abstract: true, 
    template: '<div ui-view=""></div>', 
    resolve: ['Translations' 
     , function(Translations){return Translations.loadAll();}] 
    }); 

trạng thái gốc siêu này không có bất kỳ url(không ảnh hưởng đến bất kỳ url con nào). Bây giờ, chúng tôi sẽ âm thầm tiêm đó vào mỗi tiểu bang:

$stateProvider 
    .state('home', { 
     parent: 'root', 
     url: "/home", 
     templateUrl: 'tpl.html', 
    }) 
    .state('parent', { 
     parent: 'root', 
     url: "/parent", 
     templateUrl: 'tpl.html', 
    }) 

Như chúng ta có thể thấy, chúng tôi sử dụng thiết parent - và không ảnh hưởng/mở rộng ban đầu nhà nước tên.

bang Gốc đang tải các bản dịch vào một shot thông qua phương pháp mới loadAll():

.service('Translations', ['$http' 
    ,function($http) { 
    translationsService = { 
     data : {}, 
     loadAll : function(){ 
     return $http 
      .get("translations.json") 
      .then(function(response){ 
      this.data = response.data;  
      return this.data; 
      }) 
     }, 
     get: function(section) { 
     return data[section]; 
     } 
    }; 

    return translationsService; 
}]) 

Chúng ta không cần $q ở tất cả. Trạng thái siêu gốc của chúng ta chỉ giải quyết một lần ... qua phương thức $httploadAll().Tất cả những hiện đang được nạp, và chúng tôi thậm chí có thể đặt dịch vụ đó vào $rootScope:

.run(['$rootScope', '$state', '$stateParams', 'Translations', 
    function ($rootScope, $state, $stateParams, Translations) { 
    $rootScope.$state = $state; 
    $rootScope.$stateParams = $stateParams; 
    $rootScope.Translations = Translations; 
}]) 

Và chúng ta có thể truy cập vào nó anyhwere như thế này:

<h5>Translation</h5> 
<pre>{{Translations.get($state.current.name) | json}}</pre> 

Wow ... đó là giải pháp thu lợi nhuận gần như từ mỗi tính năng đi kèm với UI-Router ... Tôi muốn nói. Tất cả được nạp một lần. Tất cả được kế thừa vì $ rootScope và xem thừa kế ... tất cả đều có sẵn ở bất kỳ trạng thái con nào ...

Kiểm tra xem tất cả here.

+0

Cảm ơn bạn đã trả lời. Thật không may, điều này sẽ không làm việc trong trường hợp của tôi khi tôi đang làm việc trên các ứng dụng quy mô rất lớn và có hàng ngàn bản dịch. Tải chúng cùng một lúc là không thể. Ngoài ra, tôi cần phải có một đối tượng có chứa các bản dịch mà tôi có thể truy cập bằng khóa. Không phải dịch vụ mà tôi gọi từ các mẫu: như {{translations.home}}. – Sray

+2

Giải pháp của tôi là một khái niệm. Bạn không phải tải tất cả. Tôi chỉ cho bạn thấy làm thế nào để làm điều đó một cách khác nhau. Chỉ cần gọi $ http trong get .. nhưng kiểm tra giải pháp của tôi ... –

Các vấn đề liên quan