Angularjs: директива перерисовки с другим шаблоном при входе пользователя в систему

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

у нас была идея загрузить боковую панель с директивой, а внутри нее иметь 2 шаблона, 1 при входе в систему и 1 при выходе из системы.

отображать и не отображать сведения о пользователе.

однако у нас есть директива sidebar, работающая с любым из двух,

App.directive('боковая панель', ['UserService', '$compile', function(User, $compile) {

var getTemplate = function() {
    console.warn(User.isLogged);
    var templateUrl = "#sidebar" + ((User.isLogged) ? '_loggedin' : '') + "_template";
    console.log('requesting template: [%s]', templateUrl);
    return $(templateUrl).html();
};

return {
    restrict: 'A',
    link: function link(scope, element, attrs) {
        var tmpl = getTemplate();
        element.html(tmpl);
        element.replaceWith($compile(element.html())(scope));
    },
    template: getTemplate()
};

}]);

и мы загружаем наши данные пользователя в службу

App.factory('UserService', [function userService() {
var User = {
    isLogged: false,
    username: ''
};
return User;
}]);

форма входа принимает это UserService как зависимость и устанавливает для него isLogged значение true

но как я могу позволить директиве перерисовать боковую панель, когда isLogged изменено?

мы делаем это правильно?


person Sander    schedule 26.07.2013    source источник


Ответы (1)


Существует этап, известный как этап компиляции, когда angular

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

По сути, вы не можете условно загружать шаблоны — он скомпилирует первый, который вы ему дадите. Если вы хотите динамически отображать свое представление, вы можете использовать два div с директивой ng-show внутри шаблона:

<div ng-show="user.isLogged">// logged in content</div>
<div ng-show="!user.isLogged">// logged out content</div>

Вы можете подумать, что вам нужно внедрить фабрику в вашу директиву — я только что попробовал это, и это не работает! Я считаю, что это связано с тем, что директивы могут устанавливать только одностороннюю и двустороннюю привязку с директивами в цепочке областей действия. Имея это в виду, я перенес пользовательский объект в область приложения:

App.controller("AppCtrl", function($rootScope, UserService) {
  $rootScope.user = UserService;
})

А затем использовал открытую область действия из директивы:

app.directive("sidebar", function() {

  return {
    restrict: "A",
    template: '<div>' +
      '<div ng-show="user.isLogged">Logged In</div>' +
      '<div ng-show="!user.isLogged">Logged Out</div></div>',
  }

})

Пользовательский объект здесь находится через цепочку областей видимости. Поскольку директива не имеет изолированной области видимости (я не объявлял свойство области действия), она находит ее по цепочке областей действия — вплоть до корневой области. Это, конечно, в некотором смысле «глобальный», и его можно легко скрыть:

$scope.user = somethingElse

Не самое красивое решение, но оно работает.

Вы также можете условно манипулировать DOM в функции ссылки или, что еще лучше, выгрузить такую ​​логику на маршрутизатор, используя вложенные шаблоны и разрешение.

person Ian Haggerty    schedule 26.07.2013
comment
Кажется, это нормально, другой вариант может быть ng-include, где URL-адрес шаблона изменен. - person shaunhusain; 26.07.2013
comment
Я пробовал ваше решение, однако я не уверен в результате, проблема в том, что версия для входа в систему, например, имеет аватар пользователя, если у меня есть атрибут src на src="/images/users/{{user.avatar}}", не имеет значения, отображается ли шоу это, он отображается, что означает, что он выдаст 404, когда свойство user.avatar не определено, есть идеи, как решить эту проблему? - person Sander; 29.07.2013
comment
Вы должны проверить ngSrc: code.angularjs.org/1.1. 5/docs/api/ng.directive:ngSrc :) Должен заботиться о нулях и правильно анализировать директивы. - person Ian Haggerty; 02.08.2013
comment
Если ваш img вложен внутри элемента уровня блока с помощью ng-show, он не должен отображаться. ng-show просто работает, установив display на none. Если он не делает то, что вы хотите, это проблема с вашей разметкой/css. - person Ian Haggerty; 02.08.2013