2014-09-23 3 views
6

Построения углового приложения, я поклонник использования нг-контроллер и пользовательские директив структурировать приложение, например:AngularJS - Управление изменение URL на несколько контроллерах/элементов пользовательского интерфейса

<nav ng-controller="NavController"></nav> 
<date-picker></date-picker> 

Я люблю эти шаблоны потому что они декларативны и очень легко следовать - вы точно знаете, где искать логику поддержки.

С другой стороны, использование ng-view или даже плагин ui-router (на мой взгляд) абстрагирует некоторые функции и затрудняет их чтение.

Однако, мой предпочтительный шаблон дает мне проблему, когда дело доходит до изменения URL-адресов в приложении по логике. Я хотел бы, чтобы каждая часть пользовательского интерфейса отвечала соответствующим образом на изменения URL-адреса, но я не знаю, куда поместить код. Я предположил, у меня есть два варианта:

  1. Ответить на $ место индивидуально изменений в каждом контроллере или директивы
  2. инкапсулировать это в каком-то другом классе или услугу, которая поддерживает ответственность за прослушивание изменение URL

Я не могу понять, как это сделать.

Первый вариант дает мне полный контроль, но я не могу воспользоваться параметрами синтаксического анализа ng-route и т. Д. Мне действительно нужно будет сворачивать самостоятельно, когда дело доходит до проверки изменений URL.

С опцией два я не могу ссылаться ни на один из моих контроллеров, потому что они уже объявлены!

В более широком смысле, я обеспокоен тем, что не найти решение этого сразу, что я должен думать о вещах неправильно. Это в корне неверно?

EDIT: Во избежание недоразумений, я очень идет о SPA, а более конкретно, это такое дело, что я пытаюсь сделать:

<nav ng-controller="NavController"><!-- more HTML here --></nav> 
<div ng-controller="VideoController"><!-- more HTML here --></div> 
<div ng-controller="CommentController" ng-show="Active"><!-- more HTML here --></div> 

Теперь предположим, что я навигации to: "/ video /: key /" - Я хочу, чтобы VideoController забирал видео-ключ и выполнял то, что ему нужно для загрузки видео. Я хочу, чтобы NavController выделил, какой пункт меню активен, и т. Д.

Если я перехожу к «/ video /: videokey/comment» - я хочу, чтобы VideoController загрузил видео, а NavController выделит, что является активным, AND CommentController для загрузки комментариев/появления в видео и т. Д.

Это та идея, с которой у меня нет головы - ответ на изменение URL-адресов в двух контроллерах, каждый из которых отвечает за отдельную часть пользовательского интерфейса в одном Применение страницы.

ответ

0

Попробуйте угловой-ui-маршрутизатор. Это может быть библиотека, в которой вы нуждаетесь. Проект на Github: https://github.com/angular-ui/ui-router

+0

Разве вы не видели причину, по которой OP не хочет этого? – Shomz

0

Я думаю, вы не говорите о SPA, одноместном приложении.

Так вопрос,

Вы хотите использовать один и тот же $routeProvider для многих страниц и обеспечить правильный контроллер для текущего пути страницы?

К сожалению, путь маршрута URL и траектория маршрута angleularjs различны, и вы не можете использовать маршрут URL для маршрута маршрута AngularJS.

Чтобы обойти, это моя идея.
Мы можем определить маршрут маршрута углов от абсолютного значения.

  1. В приложении, получить текущий путь, используя $window.location.href или $window.location.pathname

  2. Используйте этот путь внутри иначе блока.

Вот код и демо: http://plnkr.co/edit/OS38E38J11FeDS1hyHde?p=preview

angular.module('myApp', ['ngRoute']) 
    .controller('MainController', function($scope) { 
    $scope.pageName = "main page"; 
    }) 
    .controller('Page1Controller', function($scope) { 
    $scope.pageName = "page1"; 
    }) 
    .controller('Page2Controller', function($scope) { 
    $scope.pageName = "page2"; 
    }) 
    .config(function($routeProvider, $windowProvider) { 
    var otherwiseFunc = function() { 
     var absPath = $windowProvider.$get().location.href; 
     console.log('absPath', absPath); 

     var redirectTo = absPath.match(/path1/) ? '/page1' : 
     absPath.match(/path2/) ? '/page2' : 
     '/main'; 
     return { 
     redirectTo: redirectTo 
     } 
    }; 

    $routeProvider 
    .when('/main', {templateUrl: 'partial.html',controller: 'MainController'}) 
    .when('/page1', {templateUrl: 'partial.html',controller: 'Page1Controller' }) 
    .when('/page2', {templateUrl: 'partial.html',controller: 'Page2Controller' }) 
    .otherwise(
     otherwiseFunc() 
    ); 
    }); 
+0

Спасибо, что нашли время ответить. К сожалению, это не совсем то, что я имел в виду. Я обновил вопрос, чтобы, надеюсь, объяснить это немного более четко. – user888734

0

Вероятно, самый простой способ, который будет охватывать все, что нужно создать службу для обработки URL.

Служба вернет набор параметров, релевантных для каждого контроллера, который зависит от URL-адреса. Пример, он будет иметь свойство Video.id, чтобы обозначить идентификатор видео, Nav.id для обозначения ссылки нав и т.д.

Сам сервис будет очень просто - выборка по URL, разделив его на параметры, и самая трудная часть отделения какой параметр необходим для контроллера (для создания объекта, следуя правилам из приведенного выше примера).


Пример URL: /video/mySupercoolVideo/comment

Служба возвращает что-то вроде:

{ 
    video: "mySupercoolVideo", 
    nav: "comment", 
    comments: true 
    // other url-related data here 
} 

Это очень простой и простой пример (нав комментарии кажутся излишними, и я не расширялся любой из свойств верхнего уровня, поэтому нет таких вещей, как video.id и т. д.), очевидно, вы можете расширить/оптимизировать это много.

Каждый контроллер будет проверять состояние URL в начале и работать в соответствии с ответом.

Если вы хотите, вы можете также использовать для этого контроллер-оболочку, поэтому вместо того, чтобы возвращать одни и те же данные для каждого контроллера, вы просто заполнили бы одну переменную $ rootScope этими данными.

4

Это не тот ответ, который вы ищете, но это тот ответ, который вам нужно услышать (IMO).

Мнения прочь!

Вы потратите много времени на создание SPA вокруг вашего собственного макета и идей маршрутизации. Меня не удивило бы, если бы это было возможно - если вы выбрали события в соответствующей области и попросите дочерние контроллеры прослушать события изменения состояния, вы можете определить разные контроллеры, которые по-разному реагируют на изменения состояния, отображая и скрывая их содержимое, и обновляя эти содержимое, чтобы отразить текущую объектную модель (/ вещи/1 на вещи/2 на вещи/2/редактировать или что-то еще).

Это почти так, как работает ui-router, за исключением того, что вместо того, чтобы встраивать содержимое html верхнего уровня на главные страницы, он использует директивы ui-view, которые в основном обрабатывают частичные и контроллеры.

В конце дня, выполнив это, вы воспроизведете около 50% того, что делает ui-router в настоящее время. Если вам повезет, он будет работать так же, как ui-router. Если вы этого не сделаете, это будет бесполезно смешно.

У вас будет одностраничное приложение huuuuuge, которое будет очень сложно отладить. Если у вас есть все на одной странице верхнего уровня html без шаблонов, вы не сможете легко разделить проблемы или разложить поведение. Некоторый другой разработчик не сможет следить за работой, и трудно найти более тонкие ошибки с незавершенными тегами. Плюс: все это время борьба с каркасом может быть потрачена на то, чтобы заставить ваше приложение работать.

+0

Я полностью согласен. Используйте UI-Router или ngRoute. Без этого вы направляетесь по пути многих головных болей. –

1

Для чего вы хотите сделать, я вижу три варианта.

  1. Используйте $rootScope, чтобы связать ваши контроллеры вместе; сохраните переменные URL здесь. Когда они меняются, ваши контроллеры могут соответственно реагировать. Вы можете использовать $broadcast и $emit здесь для передачи сообщений, или вы можете просто посмотреть переменную $rootScope.
  2. Инкапсулируйте свою маршрутизацию в службе публикации/подписания. Служба будет обрабатывать ваши маршруты, в то время как ваши контроллеры будут соответствовать любым опубликованным изменениям. Это может быть элегантно, в зависимости от сложности поведения, которое вы хотите.
  3. Используйте вложенные контроллеры. Внешний контроллер будет обрабатывать вашу маршрутизацию; внутренние контроллеры, ваши взгляды.

Звучит так, как будто вы хотите избежать логики маршрутизации в каждом контроллере - это хорошо - но вам нужно найти способ указать нужное поведение. Если бы я попытался свернуть это с нуля, я бы предпочел, чтобы я сам опубликовал/подписал, Я предпочитаю инкапсуляцию в провайдере для чего-то вроде этого (поскольку он модульный и может быть легко использован повторно).

Это, я согласен с другими ответами здесь - было бы намного проще просто использовать ngRoute или uiRouter. Делая это, вы можете установить маршруты в одном месте (вдоль параметров маршрута) и использовать либо вложенные контроллеры/представления, либо директивы. На самом деле вы можете подумать о преобразовании объектов Video и Coments в угловые директивы.

2

Как вы предлагаете использовать ngRoute, вы можете просто ввести $rootParams -услуги в свои контроллеры и получить все текущие параметры. Если вам также нужен текущий контроллер, выбранный ngRoute, вам следует также ввести службу $route. Дополнительную информацию об использовании этих сервисов см. В разделе example in the ngRoute documentation - или предоставить (минимальную) версию вашего углового кода, чтобы дать вам пример, основанный на вашем прецеденте.

BTW: Если у вас также есть разные виды и/или макеты (например, не только видео) в вашем SPA, вы можете использовать ng-view директиву ngRoute для настройки окна просмотра для всех этих разных макетов. Таким образом, каждый макет может иметь собственный шаблон и контроллер, специфичный для макета, который может повторно использовать общие контроллеры и директивы (например, для комментариев). Опять мне нужно больше кода, чтобы дать для этого осмысленный пример.

Смежные вопросы