Оновлення URL-адреси в Angular JS без перегляду рендеринга


79

Я будую систему інформаційних панелей в AngularJS і стикаюся з проблемою встановлення URL-адреси через $location.path

На нашій інформаційній панелі ми маємо купу віджетів. Кожне з них показує збільшене розгорнутий вигляд при натисканні на нього. Ми намагаємось налаштувати глибокі посилання, щоб дозволити користувачам посилатися на інформаційну панель із розгорнутим віджетом.

На даний момент у нас є 2 маршрути, які виглядають як /dashboard/:dashboardIdі/dashboard/:dashboardId/:maximizedWidgetId

Коли користувач розгортає віджет, ми оновлюємо URL-адресу за допомогою $location.path, але це призводить до повторного відображення подання. Оскільки ми маємо всі дані, ми не хочемо перезавантажувати весь вигляд, ми просто хочемо оновити URL-адресу. Чи є спосіб встановити URL-адресу, не викликаючи повторного відтворення подання?

HTML5Modeвстановлено на true.


1
Якщо ви хочете, щоб ваші дані пережили зміни маршруту на стороні клієнта, чому б не ввести їх у службу?
Ріко

Відповіді:


133

Фактично подання відображатиметься кожного разу, коли ви змінюєте URL-адресу. Ось як $ routeProvider працює в Angular, але ви можете передати його maximizeWidgetIdяк рядок запиту, який не відображає подання повторно.

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

Коли ви натискаєте віджет, щоб розгорнути:

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

URL-адреса в адресній панелі зміниться на http://app.com/dashboard/1?maximizeWidgetId=1

Ви навіть можете спостерігати за зміною пошуку в URL-адресі (від одного віджета до іншого)

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

1
Якщо буде прийнято відповідь, я буду створювати окреме питання без будь-яких ": param" речей. Просто дурне запитання: як не рендерити вигляд.
OZ_

2
Я думаю, що angular-ui-router буде очевидним вибором у цьому випадку.
codef0rmer

1
Я використовую $routeUpdateподію. Я думаю, що це $routeChangeStartспрацьовує при переїзді в інше місце.
lucassp

@kuchumovn: На жаль, ми все ще в 2014 році. У Angular 2.0 буде оновлена ​​маршрутизація (можливо, вбудований маршрутизатор angular-ui-router), яка буде виконувати те, що ви задумали.
codef0rmer

1
@ codef0rmer, я знайшов цю відповідь не раз. Дякую! Чудова відповідь, все одно після всього цього часу!
морозний

9

Ви можете встановити для властивості reloadOnSearch $ routeProvider значення false.

Можливе повторюване запитання: Чи можете ви змінити шлях, не перезавантажуючи контролер у AngularJS?

З повагою


Здається, це копія. На жаль, схоже, у них однакова проблема, якщо це частина шляху URL-адреси, а не змінна запиту, вона оновлюється.
Ian Muir

Ні, це не дублікат.
OZ_

Це не дублікат, оскільки пов’язане питання стосується не перезавантаження контролера, а це не перезавантаження шаблону. Рішення у зв’язаному питанні призведе до перезавантаження подання.
Лайош Месарос


3

Для подібного сценарію ми використовуємо Angular UI Router замість вбудованих маршрутів. Здається, це не робить повторне створення екземпляра контролера і не відображає весь вигляд.


2
Ви пробували використовувати $state.transitionTo()замість $location.path()?
DreamSonic

1
Я взагалі не змінюю $ location.path (), де $state.transitionTo()тоді писати ?
OZ_

Цитата: "Коли користувач розгортає віджет, ми оновлюємо URL-адресу за допомогою location.path, але це призводить до повторного відображення подання." Замість того, щоб змінювати шлях, вам слід зателефонувати, $state.transitionTo()який, у свою чергу, оновить хеш URL-адреси.
DreamSonic

Ідея полягає в тому, що у вас має бути два вкладених стану: один для вашої інформаційної панелі, а другий для розгорнутого віджета. Коли ви переходите з батьківського стану в дочірній, буде відтворений лише дочірній вигляд, а не батьківський.
DreamSonic

3

Я усвідомлюю, що це давнє запитання, але оскільки мені знадобився добрий півтора дні, щоб знайти відповідь, тож ось що.

Вам не потрібно перетворювати свій шлях у рядки запитів, якщо ви використовуєте angular-ui-router .

В даний час через те, що може розглядатися як помилка , встановлення reloadOnSearch: falseстану призведе до можливості зміни маршруту без перезавантаження подання. Користувач GitHub lmessinger був навіть досить люб’язний, щоб надати демонстрацію. Ви можете знайти посилання з його коментаря, зв’язаного вище.

В основному все, що вам потрібно зробити, це:

  1. Використовуйте ui-routerзамістьngRoute
  2. У своїх штатах заявіть про тих, кого хочете reloadOnSearch: false

У моєму додатку у мене є перелік категорій, з якого ви можете перейти до іншої категорії, використовуючи такий стан:

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

Це воно. Сподіваюся, це допомагає!


2

Як я це реалізував:
(моє рішення переважно для випадків, коли вам потрібно змінити весь маршрут, а не підрозділи)

У мене є сторінка з меню (menuPage), і дані не слід очищати під час навігації (на кожній сторінці багато входів, і користувач буде дуже нещасливим, якщо дані випадково зникнуть).

  1. вимкнути $ routeProvider
  2. у контролері mainPage додайте два div з атрибутом нестандартної директиви - кожна директива містить лише 'templateUrl' та 'scope: true'

     <div ng-show="tab=='tab_name'" data-tab_name-page></div>
    
  3. Контролер mainPage містить рядки для імітації маршрутизації:

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

Це все. Трохи потворно мати окрему директиву для кожної сторінки, але використання динамічного templateUrl (як функції) в директиві провокує повторний візуалізацію сторінки (і втрату даних входів).


0

Якщо я правильно зрозумів ваше запитання, ви хочете,

  1. Розгорніть віджет, коли користувач знаходиться на / dashboard /: dashboardId, і він розгортає віджет.
  2. Ви хочете, щоб у користувача була можливість повернутися до / dashboard /: dashboardId /: maximizedWidgetId і все одно бачити віджет максимально.

Ви можете налаштувати лише перший маршрут у routerConfig і використовувати RouteParams, щоб визначити, чи передано розгорнутий віджет у параметри в контролері цього налаштованого маршруту, та максимізувати той, що передається як параметр. Якщо користувач максимізує його вперше, надішліть URL-адресу цього розгорнутого подання з maximizedWidgetId в інтерфейсі.

Поки ви використовуєте $ location (який є просто обгорткою над об'єктом власного розташування) для оновлення шляху, він оновлює вигляд.


1
Не тільки $ location оновить огляд. ng-include також, навіть не змінюючи $ location.
OZ_

@OZ_ Я не пропонував ngInclude, оскільки це просто зміна стану всередині подання, я просто пропоную щось на зразок ng-if, що було б пов'язано з функцією, яка може зрозуміти routeParams
Sivakumar Kailasam

0

У мене є ідея використовувати

window.history.replaceState ('Об'єкт', 'Заголовок', '/ new-url');

Якщо ви зробите це, і трапиться цикл перетравлення, це повністю зіпсує речі. Однак, якщо ви встановите правильну URL-адресу, яка, як очікує кутова, це нормально. Отже, теоретично ви можете зберегти правильну URL-адресу, яку очікує кутова, і скинути її безпосередньо перед тим, як дізнатись, що дайджест загоряється.

Однак я це не тестував.


-2

Нижче код дозволить вам змінити URL-адресу без переспрямування, наприклад: http: // localhost / # / 691? Foo? Bar? Blabla

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

Але коли ви перейдете на http: // localhost / # / 692 , ви будете перенаправлені.


Я не розумію, навіщо тут додавати іншу відповідь.
gsamaras

1
це примітка до історії.
abc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.