Новое в Angular: должно ли это быть в сервисе или в контроллере?

0

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

Использование контроллера, прикрепленного к директиве

Посмотреть

<select ng-model="type" ng-change="updateDisplay()">
    <option value="typeOne">One</option>
    <option value="typeTwo">Two</option>
    <option value="typeThree">Three</option>
</select>

<select ng-model="subType" ng-change="updateDisplay()">
    <option value="subTypeOne">One</option>
    <option value="subTypeTwo">Two</option>
    <option value="subTypeThree">Three</option>
</select>

...

<div ng-repeat="(key, value) in selectedData">
     {{key}}, {{value}}
</div>

контроллер

$scope.type = 'typeOne';
$scope.subType = 'subTypeOne';
$scope.selectedData = null;

$scope.updateDisplay = function() {
   //$scope.data is a large object of data passed into the directive, but not important to define for this post 
   $scope.selectedData = $scope.data[$scope.type][$scope.subType];
}

$scope.updateDisplay();  // call on page load to populate with defaults

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

ng-change="setSelectedType({type:type})"

а затем, возможно, потребуется выполнить еще одну функцию после запуска функции "Сеттер", чтобы пересчитать динамическое значение для выбранных данных. (эквивалент выполнения updateDisplay() выше.

Мой общий вопрос заключается в том, что перемещение всей этой логики на службу даже имеет смысл? Я должен был бы написать getters и seters со стороны службы и называть их каждый раз по ng-change в дополнение к тому, чтобы служба затем возвращала отфильтрованные данные. И наоборот, если это делается в контроллере, нам не нужно создавать какие-либо "сеттеры/геттеры" для переменных, потому что они привязаны к области и обновляются автоматически. (и для меня весь смысл использования каркаса как углового).

Не сделав этот вопрос ТОО самоуверенным, может ли кто-то с Угловым опытом говорить об этом?

Теги:

2 ответа

0
Лучший ответ

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

Я думаю, что угловой способ - использовать наблюдателей.

scope.$watch('subType',function(subType) {
   scope.selectedData = data[scope.type || 'defaultKey'][subType || 'defaultKey'];
});

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

Другая проблема - scope.data и если это действительно должно быть в области. Если в шаблоне нет прямого связывания с ним, то не оставляйте его вне области видимости. Это помогает сохранить масштаб, связанный с тем, что в шаблоне. Позже, когда вы отлаживаетесь в браузере и смотрите на область $($0).scope() вы увидите только то, что важно.

Если у вас есть data в области. Вы могли бы просто сделать это. Угловая ошибка не будет отсутствовать. Шаблон будет просто не повторяться, если выбор не будет действительным.

<div ng-repeat="(key, value) in data[type][subType]">
    {{key}}, {{value}}
</div>
0

Лично я не верю в жесткие и быстрые правила развития, но, как правило, большинство разработчиков согласятся:

  • У вас должны быть тонкие (минимальные) контроллеры, если вообще
  • Ваша бизнес-логика должна быть в сервисах
  • Директивы должны быть только для DOM-манипуляций

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

Если вы использовали услугу, вы просто вводите директиву и услугу в свой новый контроллер (и связываете их через контроллер) - работа выполнена!

Наконец, вы хотите ограничить взаимодействие между директивой и контроллером с четко определенным интерфейсом. Используйте свойство "scope" в директиве для этого.

  • 0
    Я ценю ваш ответ. Можете ли вы добавить некоторые детали в свой ответ? Что вы подразумеваете под «бизнес-логикой»? Будет ли в моем примере "updateDisplay ()" считаться такими? Также я не уверен, почему мне когда-либо пришлось бы переписывать свой код, если бы я хотел использовать свою директиву на другой странице. Директива определяется с помощью templateUrl, контроллера, уникального для директивы, и области действия {}, которая позволяет передавать большой объект данных в него. Разве я не смогу снова использовать директиву на любой другой странице?
  • 0
    Нет проблем! Вы описали бизнес-логику с помощью термина «логика» в своем вопросе: геттеры / сеттеры, манипулирование данными и т. Д. Если бы этот код был в контроллере, вам пришлось бы переписать его, если директива была привязана к другому контроллеру. Если бы код был в сервисе, вы бы этого не сделали.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню