2014-10-09 2 views
0

Я изо всех сил стараюсь придумать правильную Угловую идиому, и я почувствовал, что путь, по которому я спускаюсь, не чист. Чтобы сформировать мой сценарий с надуманным примером:Как обрабатывать события между несколькими директивами и контроллером?

  • Рассмотрите Угловой контроллер, который называется AlbumController.
  • AlbumController имеет свойство объем, который является массивом объектов альбома:

    $scope.albums = [ 
        { 
        title : "Album 1", 
        artist : "Artist 1" 
        }, 
        ... 
    ] 
    
  • Я использую ng-repeat спаренный с пользовательской директивы макет альбомы:

    <div ng-repeat="album in albumns"> 
        <div fresh-album album="album"></div> 
    </div> 
    
  • И шаблон директивы устанавливает свойство для этого объекта альбома:

    module.directive('freshAlbum', function() { 
        return { 
        template : '<button ng-click="album.selected = !album.selected">Click</button>', 
        scope : { album = '=' }, 
        ... 
        }; 
    }); 
    
  • Примечание. Причиной добавления атрибута selected является то, что при щелчке альбома выбираются пользовательские стили для указания альбома, который добавляется к элементу.

  • Что я хотел бы сделать: когда выбран альбом, deselect другой выбранный альбом (например, если выбран альбом 1, и пользователь выбирает альбом 2, мне нужен альбом 1 для снятия выделения).

Моя первая мысль этого была иметь $watch в AlbumController следить за изменениями альбома:

var selectedAlbum = -1; // Keeping track of the currently selected album 
$scope.$watch('albums', function(newValue) { 
    angular.forEach($scope.albums, function(album, i) { 
    if (selectedAlbum === -1 && album.selected) { 
     selectedAlbum = i;  // No previously selected albums 
    } else if (selectedAlbum === i && album.selected) { 
     album.selected = false; // Previously selected album; deselect it 
    } else if (album.selected) { 
     selectedAlbum = i;  // Newly selected album 
    } 
    }); 
}); 

Однако, поскольку я «де-выбрав пункт» альбомы в $watch обратного вызова, это вызывает другой $watch, отменяя тем самым новый выбранный альбом. В этот момент я остановился, потому что чувствовал, что приближаюсь к этому.

Альтернативная идея, которую я имел, заключалась в том, чтобы директива freshAlbum опубликовала событие «выбора», на которое реагирует контроллер. Является ли подход, как этот более угловатыми-эск "?

ответ

2

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

module.directive('freshAlbum', function() { return { 
    template : '<button ng-click="album.selected = !album.selected; albumIsClickedEvent();">Click</button>', 
    scope : { album : '=' 
       albumIsClicked: "&"}, 
    ... }; }); 

<div ng-repeat="album in albumns"> 
    <div fresh-album album="album" album-is-clicked="albumIsClickedEvent"></div> 
</div> 

И в контроллере, вы можете реализовать функцию albumIsClickedEvent к делать то, что вы хотите достичь (закрыть все открытые альбомы и т.д.).

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

+1

Я хотел бы добавить эту функцию в качестве второго параметра директивы, чтобы сделать его умным. –

+1

T ypically, когда я делаю что-то подобное, я просто делаю все в этом методе: 'ng-click = 'select (album)' Так что один метод в основном отменяет выбор всех альбомов, а затем устанавливает правильный для выбранного. – threeve

+1

Вы правы; лучше написать функцию в объявлении директивы, а не записывать ее как встроенную функцию в свой шаблон. – cubbuk

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