Cập nhật URL trong Angular JS mà không cần hiển thị lại chế độ xem


79

Tôi đang xây dựng hệ thống bảng điều khiển trong AngularJS và tôi đang gặp sự cố với việc đặt url qua $location.path

Trong bảng điều khiển của chúng tôi, chúng tôi có một loạt các tiện ích con. Mỗi hiển thị một chế độ xem được tối đa hóa lớn hơn khi bạn nhấp vào nó. Chúng tôi đang cố gắng thiết lập liên kết sâu để cho phép người dùng liên kết đến trang tổng quan với tiện ích con được tối đa hóa.

Hiện tại, chúng tôi có 2 tuyến đường giống như /dashboard/:dashboardId/dashboard/:dashboardId/:maximizedWidgetId

Khi người dùng tối đa hóa một tiện ích, chúng tôi cập nhật url bằng cách sử dụng $location.path, nhưng điều này khiến chế độ xem hiển thị lại. Vì chúng tôi có tất cả dữ liệu, chúng tôi không muốn tải lại toàn bộ chế độ xem, chúng tôi chỉ muốn cập nhật URL. Có cách nào để đặt url mà không khiến chế độ xem hiển thị lại không?

HTML5Modeđược đặt thành true.


1
Nếu bạn muốn dữ liệu của mình tồn tại qua những thay đổi về lộ trình ở phía máy khách, tại sao không đẩy nó vào một dịch vụ?
Riko

Câu trả lời:


133

Trên thực tế, một chế độ xem sẽ được hiển thị mỗi khi bạn thay đổi url. Đó là cách $ routeProvider hoạt động trong Angular nhưng bạn có thể chuyển maximizeWidgetIddưới dạng một chuỗi truy vấn không hiển thị lại chế độ xem.

App.config(function($routeProvider) {
  $routeProvider.when('/dashboard/:dashboardId', {reloadOnSearch: false});
});

Khi bạn nhấp vào một tiện ích để tối đa hóa:

<a href="#/dashboard/1?maximizeWidgetId=1">Maximum This Widget</a>
or
$location.search('maximizeWidgetId', 1);

URL trong thanh địa chỉ sẽ thay đổi thành http://app.com/dashboard/1?maximizeWidgetId=1

Bạn thậm chí có thể xem khi tìm kiếm thay đổi trong URL (từ tiện ích con này sang tiện ích con khác)

$scope.$on('$routeUpdate', function(scope, next, current) {
   // Minimize the current widget and maximize the new one
});

1
Nếu nó được chấp nhận câu trả lời, tôi sẽ tạo một câu hỏi riêng biệt mà không có bất kỳ thứ ": param" nào. Chỉ là một câu hỏi ngu ngốc: làm thế nào để không hiển thị lại chế độ xem.
OZ_

2
Tôi nghĩ rằng góc cạnh-ui-router sẽ là một lựa chọn hiển nhiên trong trường hợp đó.
codef0rmer,

1
Tôi đang sử dụng $routeUpdatesự kiện. Tôi nghĩ rằng $routeChangeStartnó sẽ được kích hoạt khi chuyển đến một vị trí khác.
lucassp,

@kuchumovn: Thật không may, chúng tôi vẫn đang ở trong năm 2014. Angular 2.0 sẽ có một định tuyến được cải tiến (có thể được tích hợp sẵn góc cạnh-ui-router) để thực hiện những gì bạn dự định.
codef0rmer

1
@ codef0rmer, tôi đã tìm thấy câu trả lời này hơn một lần. Cảm ơn! Câu trả lời tuyệt vời, vẫn còn sau tất cả thời gian!
băng giá

9

Bạn có thể đặt thuộc tính reloadOnSearch của $ routeProvider thành false.

Câu hỏi trùng lặp có thể xảy ra: Bạn có thể thay đổi đường dẫn mà không cần tải lại bộ điều khiển trong AngularJS không?

Trân trọng


Có vẻ như nó là một bản sao. Thật không may, có vẻ như chúng có cùng một vấn đề, miễn là nó là một phần của đường dẫn url, không phải là một biến truy vấn, nó sẽ làm mới.
Ian Muir

Không, nó không trùng lặp.
OZ_

Nó không phải là một bản sao, vì câu hỏi được liên kết là về việc không tải lại bộ điều khiển và đây là về việc không tải lại mẫu. Giải pháp trong câu hỏi được liên kết sẽ làm cho chế độ xem được tải lại.
Lajos Meszaros


3

Chúng tôi đang sử dụng Angular UI Router thay vì các tuyến tích hợp sẵn cho một trường hợp tương tự. Nó dường như không khởi tạo lại bộ điều khiển và hiển thị lại toàn bộ chế độ xem.


2
Bạn đã thử sử dụng $state.transitionTo()thay vì $location.path()?
DreamSonic,

1
Tôi không thay đổi $ location.path (), $state.transitionTo()sau đó nên viết ở đâu?
OZ_

Trích dẫn: "Khi người dùng tối đa hóa tiện ích, chúng tôi cập nhật url bằng cách sử dụng location.path, nhưng điều này khiến chế độ xem hiển thị lại." Thay vì thay đổi đường dẫn, bạn nên gọi đường dẫn $state.transitionTo()đó sẽ cập nhật băm url.
DreamSonic,

Ý tưởng là bạn nên có hai trạng thái lồng nhau: một cho trang tổng quan của bạn và một cho tiện ích con được tối đa hóa của bạn. Khi bạn điều hướng từ trạng thái gốc sang trạng thái con, chỉ chế độ xem con sẽ hiển thị lại, không phải chế độ xem chính.
DreamSonic

3

Tôi nhận ra đây là một câu hỏi cũ, nhưng vì tôi đã mất một ngày rưỡi để tìm ra câu trả lời, vì vậy tôi bắt đầu.

Bạn không cần phải chuyển đổi đường dẫn của mình thành các chuỗi truy vấn nếu bạn sử dụng angle-ui-router .

Hiện tại, do những gì có thể được coi là lỗi , việc đặt reloadOnSearch: falsetrên trạng thái sẽ dẫn đến việc có thể thay đổi tuyến đường mà không cần tải lại chế độ xem. Người dùng GitHub lmessinger thậm chí còn tử tế để cung cấp một bản demo về nó. Bạn có thể tìm thấy liên kết từ bình luận của anh ấy được liên kết ở trên.

Về cơ bản, tất cả những gì bạn cần làm là:

  1. Sử dụng ui-routerthay vìngRoute
  2. Ở các tiểu bang của bạn, hãy khai báo những điều bạn muốn reloadOnSearch: false

Trong ứng dụng của mình, tôi có một chế độ xem danh sách danh mục, từ đó bạn có thể đến một danh mục khác bằng trạng thái như sau:

$stateProvider.state('articles.list', {
  url: '{categorySlug}',
    templateUrl: 'partials/article-list.html',
    controller: 'ArticleListCtrl',
    reloadOnSearch: false
  });

Đó là nó. Hi vọng điêu nay co ich!


2

Cách tôi đã triển khai nó:
(giải pháp của tôi chủ yếu dành cho các trường hợp bạn cần thay đổi toàn bộ lộ trình, không phải các phần phụ)

Tôi có trang có menu (menuPage) và dữ liệu không được làm sạch trên điều hướng (có rất nhiều đầu vào trên mỗi trang và người dùng sẽ rất không hài lòng nếu dữ liệu vô tình biến mất).

  1. tắt $ routeProvider
  2. trong bộ điều khiển mainPage thêm hai div với thuộc tính chỉ thị tùy chỉnh - mỗi chỉ thị chỉ chứa 'templateUrl' và 'scope: true'

     <div ng-show="tab=='tab_name'" data-tab_name-page></div>
    
  3. mainPage controller chứa các dòng để mô phỏng định tuyến:

    if (!$scope.tab && $location.path()) {
        $scope.tab = $location.path().substr(1);
    }
    $scope.setTab = function(tab) {
        $scope.tab = tab;
        $location.path('/'+tab);
    };
    

Đó là tất cả. Hơi xấu khi có chỉ thị riêng biệt cho từng trang, nhưng việc sử dụng templateUrl động (dưới dạng hàm) trong chỉ thị gây ra kết xuất trang (và làm mất dữ liệu đầu vào).


0

Nếu tôi hiểu đúng câu hỏi của bạn, bạn muốn,

  1. Tối đa hóa tiện ích con khi người dùng ở trên / dashboard /: dashboardId và anh ta tối đa hóa tiện ích.
  2. Bạn muốn người dùng có khả năng quay lại / dashboard /: dashboardId /: maximizedWidgetId và vẫn thấy tiện ích được tối đa hóa.

Bạn chỉ có thể định cấu hình tuyến đường đầu tiên trong routerConfig và sử dụng RouteParams để xác định xem tiện ích con được tối đa hóa có được chuyển vào các tham số trong bộ điều khiển của tuyến được định cấu hình này hay không và tối đa hóa tuyến được truyền làm tham số. Nếu người dùng đang tối đa hóa nó lần đầu tiên, hãy chia sẻ url tới chế độ xem được tối đa hóa này với MaximumWidgetId trên giao diện người dùng.

Miễn là bạn sử dụng $ location (chỉ là một trình bao bọc trên đối tượng vị trí gốc) để cập nhật đường dẫn, nó sẽ làm mới chế độ xem.


1
Không chỉ $ location sẽ làm mới chế độ xem. ng-include cũng sẽ, ngay cả khi không thay đổi vị trí $.
OZ_

@OZ_ Tôi không đề nghị ngInclude vì đây chỉ là một sự thay đổi trạng thái bên trong một cái nhìn Tôi chỉ thấy có lẽ cái gì đó như Ng-nếu mà sẽ được gắn với một chức năng mà có thể tìm ra routeParams
Sivakumar Kailasam

0

Tôi có một ý tưởng để sử dụng

window.history.replaceState ('Đối tượng', 'Tiêu đề', '/ new-url');

Nếu bạn làm điều này và một chu kỳ tiêu hóa xảy ra, nó sẽ hoàn toàn xáo trộn mọi thứ. Tuy nhiên, nếu bạn đặt nó trở lại đúng url mà góc mong đợi thì nó vẫn ổn. Vì vậy, về lý thuyết, bạn có thể lưu trữ đúng url mà góc mong đợi và đặt lại nó ngay trước khi bạn biết thông báo kích hoạt.

Tôi đã không thử nghiệm điều này mặc dù.


-2

Đoạn mã dưới đây sẽ cho phép bạn thay đổi url mà không cần chuyển hướng như: http: // localhost / # / 691? Foo? Bar? Blabla

for(var i=0;i<=1000;i++) $routeProvider.when('/'+i, {templateUrl: "tabPages/"+i+".html",reloadOnSearch: false});

Nhưng khi bạn thay đổi thành http: // localhost / # / 692 , bạn sẽ được chuyển hướng.


Tôi không hiểu tại sao phải thêm câu trả lời khác ở đây.
gsamaras

1
nó là một ghi chú cho lịch sử.
abc
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.