2015-04-27 18 views
8

Tôi đang tạo một ứng dụng có trạng thái động và đôi khi tôi cần phải giải quyết tên trạng thái từ url.ANGULAR-UI-ROUTER: Giải quyết trạng thái từ URL

ví dụ: Tôi có /dashboard/user/12268 và tôi cần nhận trạng thái 'dashboard.user'.

Có cách nào để thực hiện điều này với các công cụ được cung cấp bởi ui-router không? Tôi không thể tìm hiểu cách thực hiện việc này ngay bây giờ ...

Tôi đang tạo ứng dụng có tải mô-đun động với requireJS. Lúc đầu không có vấn đề gì vì người dùng được gửi đến trạng thái đăng nhập. Sau khi đăng nhập, tôi sử dụng chỉ cần tải các trạng thái mà người dùng có quyền truy cập. Nhưng khi người dùng tải lại trang, tôi tải lại mô-đun và cần phải giải quyết url tới trạng thái và có sự cố. Tôi đã bắt đầu thử với urlMatcherFactory nhưng không thể giải quyết chúng.

Trạng thái được tải sau độ phân giải URL.

Dòng chảy được (sau khi refresh trang http://localhost:8090/index.html#/dashboard/user/12268):

  • bootstrap ứng dụng (không có bang)
  • vào thời điểm này, ui-router đã được tải
  • có được trạng thái người dùng có quyền truy cập đến và đăng ký chúng (các tiểu bang này được đăng ký sau giai đoạn cấu hình)
  • tìm hiểu xem tôi có một tiểu bang khớp với url đã cho để chuyển hướng đến đó hay không. Đây là nơi tôi bị kẹt.

Để tải trạng thái sau khi khởi động ứng dụng, tôi đã sử dụng biến thể Ben Nadel's solution bao gồm các trạng thái và hằng số.

data-main trong RequireJS tôi có mã khởi tạo này:

require.config({ 
 
    // REQUIREJS CONFIGURATION 
 
}); 
 

 
require(['app'], function (app) { 
 
    app.bootstrap(document); 
 

 
    var ng = angular.injector(['ng']); 
 
    var $window = ng.get('$window') 
 
    var $q = ng.get('$q'); 
 

 
    var appStorage = $window.localStorage; 
 
    var loadedManifests; 
 

 
    try { 
 
     loadedManifests = JSON.parse(appStorage.getItem('loadedManifests')); 
 
    } catch(e) { 
 
     loadedManifests = []; 
 
    } 
 

 
    if (!angular.isArray(loadedManifests) || loadedManifests.length === 0) { 
 
     $q.all([ 
 
       app.loadManifest('login/manifest'), //loadMainfest function loads the states for login 
 
       app.loadManifest('logout/manifest') //load states for logout 
 
      ]) 
 
      .then(function() { 
 
       app.injector.get('$rootScope').$evalAsync(function() { 
 
        app.injector.get('$state').go('login'); 
 
       }); 
 
      }); 
 
    } else { 
 
     var promisesArray = []; 
 

 
     for(var i = 0; loadedManifests[i]; i++) { 
 
      promisesArray.push(app.loadManifest(loadedManifests[i])); //load all manifests registered on localstorage 
 
     } 
 

 
     $q.all(promisesArray).then(function(){ 
 
      //TODO: Stuck. Get URL from querystring and resolve to valid state, or redirect to /login 
 
     }); 
 
    } 
 
});

Chức năng loadManifest đăng ký tất cả sau bootstrap yếu tố trên ứng dụng của tôi (dịch vụ, nhà máy, điều khiển, thiết bị định tuyến, ...).

Nhờ sự giúp đỡ của bạn,
Alx

+2

Hãy đăng những gì bạn có cho đến nay – tim

+0

Tôi đang tạo ứng dụng có tải mô-đun động với requireJS. Lúc đầu không có vấn đề gì vì người dùng được gửi đến trạng thái đăng nhập. Sau khi đăng nhập, tôi sử dụng chỉ cần tải các trạng thái mà người dùng có quyền truy cập. Nhưng khi người dùng tải lại trang, tôi tải lại mô-đun và cần phải giải quyết url đến trạng thái và có sự cố. Tôi đã bắt đầu thử với urlMatcherFactory nhưng không thể giải quyết chúng Trạng thái được tải sau khi độ phân giải URL –

+0

Giao diện người dùng trên giao diện người dùng trong tương lai có thể quản lý kịch bản của bạn cho bạn: http://christopherthielen.github.io/ui-router -extras/#/future –

Trả lời

-2

Trạng thái hiện tại có thể thu được từ dịch vụ nhà nước $. như $state.current Kiểm tra api này http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state

+0

nó có thể được thêm vào làm chú thích –

+0

@pankajparkar câu lệnh này chứa câu trả lời cùng với tham chiếu đến api doc. tại sao nó sẽ là một bình luận? –

+0

cách giải quyết câu hỏi của OP .. bạn có thể giải thích cho tôi –

1

Cuối cùng tôi đã có để thực hiện một sự thay đổi nhỏ về dịch vụ $state ui-router để có được giải pháp.

Kết quả là các trạng thái được lưu trữ trong dịch vụ có thêm thông tin được cung cấp theo phương thức $state.get().Vì vậy, tôi lặp qua chúng để có được một nhà nước phù hợp với URL của tôi:

/** 
 
* @ngdoc function 
 
* @name ui.router.state.$state#fromUrl 
 
* @methodOf ui.router.state.$state 
 
* 
 
* @description 
 
* A method to resolve a state and its parameters from a given URL 
 
* 
 
* @returns {boolean} Returns a state that matches with the given URL, or undefined if no match 
 
*/ 
 
$state.fromUrl = function(url) { 
 
    if(!angular.isString(url)) { 
 
    //Only valid strings allowed 
 
    return undefined; 
 
    } 
 
    
 
    
 
    var keys = objectKeys(states); 
 
    //Iterate over all states 
 
    for(var i = 0; i < keys.length; i++) { 
 
    var state = states[keys[i]]; 
 
    var stateArgs = state.url.exec(url); 
 

 
    //If the state's URL does not match then stateArgs will be false 
 
    if(!!stateArgs) { 
 
     return { 
 
     name: state.name, 
 
     args: stateArgs 
 
     } 
 
    } 
 
    } 
 

 
    return undefined; 
 
};

Kính trọng,
Alx

+0

nơi "tiểu bang" đến từ trong objectKeys (tiểu bang)? –

14

https://github.com/angular-ui/ui-router/issues/1651

Bạn có thể phơi bày việc thực hiện tình trạng nội bộ của sử dụng móc .decorator trên $stateProvider. Bạn có thể trang trí bất kỳ tài sản nào của nhà xây dựng nhà nước; Tôi đã chọn 'phụ huynh' tùy ý.


app.config(function($stateProvider) { 
    $stateProvider.decorator('parent', function (internalStateObj, parentFn) { 
    // This fn is called by StateBuilder each time a state is registered 

    // The first arg is the internal state. Capture it and add an accessor to public state object. 
    internalStateObj.self.$$state = function() { return internalStateObj; }; 

    // pass through to default .parent() function 
    return parentFn(internalStateObj); 
    }); 
}); 

Bây giờ bạn có thể truy cập đối tượng trạng thái nội bộ sử dụng .$$state(), ví dụ

var publicState = $state.get("foo"); 
var privateInternalState = publicState.$$state(); 

Thứ hai, vòng lặp qua mỗi tiểu bang trong $ state.get() và kiểm tra chúng đối với đoạn URL của bạn.

angular.forEach($state.get(), function(state) { 
    var privatePortion = state.$$state(); 
    var match = privatePortion.url.exec(url, queryParams); 
    if (match) console.log("Matched state: " + state.name + " and parameters: " + match); 
}); 
+0

Đó là bằng chứng tuyệt vời về thiết kế, tốt. Khả năng mở rộng ... –

+0

Tốt nhất. Dung dịch. Không bao giờ. Cảm ơn bạn! –

+3

Trong phần tìm kiếm, thêm trả về 'if (! State. $$ state);' sẽ là tốt, vì tôi có trạng thái trừu tượng _global_ không có thuộc tính đó và gây ra lỗi. – Parziphal

0

Để có được @ Chris T giải pháp để làm việc cho tôi, tôi đang làm điều này bên trong một dịch vụ:

app.service('Helper', ['$state', '$location', 
    function($state, $location){ 

     var services = {}; 

     services.stateIs = function(state_name){ 
      var current_path = $location.$$path; 
      var state = $state.get(state_name); 

      if(state){ 
       var state_regexp = state.$$state().url.regexp; 
       return state_regexp.test(current_path); 
      }else{ 
       return false; 
      } 
     } 

     return services; 
    } 
]); 

Vì vậy, sau đó tôi có thể tiêm Helper bất cứ đâu và làm như sau:

if(Helper.stateIs('app.user')){ 
    //yeah 
} 
Các vấn đề liên quan