2014-10-15 2 views
0

Я шаблон, который содержит (частично) точно так же содержание повторяется два или три раза с небольшими изменениями в привязки, например:повтор содержания (суб-шаблон) в AngularJS

<div class="xyz-state0" data-ng-hide="data.error || !data.states[0].name"> 
    <div class="xyz-content"> 
     <img data-ng-src="{{data.states[0].image}}" width="48" height="48"> 
     <span>{{data.states[0].name}}</span> 
    </div> 
</div> 
<div class="xyz-state1" data-ng-hide="data.error || !data.states[1].name"> 
    <div class="xyz-content"> 
     <img data-ng-src="{{data.states[1].image}}" width="48" height="48"> 
     <span>{{data.states[1].name}}</span> 
    </div> 
</div> 

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

В основном я хочу что-то похожее на ngRepeat, но я не могу использовать это по следующим причинам:

  • мне нужна специфическая (и другое) стиль на каждых родительских делах.
  • Мне нужно отобразить определенное количество div (2 в этом случае, 3 в другом) независимо от того, существуют они или нет в области (т. Е. Data.states может содержать только один элемент, но он все еще нуждается для создания обоих div).
  • В другом случае предметы должны быть выведены из строя (сначала 1, затем 0, затем 2).

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

<div class="xyz-state0" data-ng-include="'state.tpl.html'" data-ng-init="state=data.state[0]"></div> 
<div class="xyz-state1" data-ng-include="'state.tpl.html'" data-ng-init="state=data.state[1]"></div> 

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

ответ

0

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

state.tpl.html:

<div class="xyz-content" data-ng-show="state.name"> 
    <img data-ng-src="{{state.image}}" width="48" height="48" /> 
    <span>{{state.name}}</span> 
</div> 

view.tpl.HTML:

<div data-xyz-state="data.states[0]" class="xyz-state0" 
     data-ng-hide="data.error"></div> 
    <div data-xyz-state="data.states[1]" class="xyz-state1" 
     data-ng-hide="data.error"></div> 

app.js:

app.directive('xyzState', [function() { 
    return { 
     templateUrl: 'state.tpl.html', 
     scope: { 
      state: '=xyzState', 
     }, 
    }; 
}]); 

Интересно, что не работать, если я пытаюсь объявить о введении элемента в <xyz-state ...> вместо <div data-xyz-state="" ...>, несмотря на документы говорят, что это тоже должно работать. Я предполагаю, что здесь есть что-то вроде проверки.

+0

вам нужно будет сделать 'ограничение: 'E'', если вы хотите использовать его как элемент вместо атрибута. И имейте в виду, что вы можете установить класс программно, если вы действительно выполняете состояния [0] как state0 и так далее. Для этого просмотрите ng-class. – pfooti

+0

Я использовал 'ng-class', чтобы программно программировать классы в некоторых других контекстах, но я не уверен, как это поможет здесь. Если вы не предлагаете что-то вроде 'ng-class = '{' xyz-state0 ': $ index == 0,' xyz-state1 ': $ index == 1}" '- Я думаю, что это гораздо менее читаемо, чем то, что У меня есть. (Хотя я признаю, что это позволило бы мне использовать 'ng-repeat' для этого случая, хотя и не тот.) – Miral

1

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

<state ng-repeat="item in data.states" item="item">. 

В качестве альтернативы, если пользовательские директивы слишком избыточен (зависит от того, будете ли вы быть повторно использовать этот вид компонент в другом месте, в основном), вы могли бы просто положите в ng- повторить на весь div. Единственная реальная проблема - это материал класса = «xyz-stateN», но я уверен, вы могли бы разобраться с использованием ng-класса.

EDIT:

если вы делаете нг-повтора, вы можете просто использовать ключ $ индекса (до тех пор, пока вы всегда подсчитывая от нуля и состояние класса совпадает с индексом). Что-то вроде

<div ng-class="{{'xyz-state'+$index}}" ng-repeat="state in data.states" data-ng-hide="data.error || !state.name"> 
    <div class="xyz-content"> 
     <img data-ng-src="{{state.image}}" width="48" height="48"> 
     <span>{{state.name}}</span> 
    </div> 
</div> 

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

+0

Думаю, вам нужно перечитать мой вопрос. Я упомянул, что он не будет использоваться в другом месте, и что ng-repeat не делает то, что я хочу. – Miral

+0

Я согласен с решением ng-repeat. Ваша проблема больше связана с массивом, чем с представлением. Если вы сосредоточились на создании массива состояний в правильном порядке/формате с помощью настраиваемых (или предварительно построенных) фильтров, вы можете получить гладкое решение. –

0

Как и в случае с FYI, я позже пересмотрел этот код и решил сделать это следующим образом: (Я даю свой первоначальный ответ, поскольку это больше похоже на то, что я изначально просил, и оба они кажутся разумными в разные случаи.)

view.tpl.html

<div data-ng-repeat="state in data.states" data-ng-if="!data.error" 
     data-ng-class="state.class"> 
     <div class="xyz-content" data-ng-show="state.name"> 
      <img data-ng-src="{{state.image}}" width="48" height="48" /> 
      <span>{{state.name}}</span> 
     </div> 
    </div> 

app.js

... 
while ($scope.data.states.length < 2) 
    $scope.data.states.push({}); 
$scope.data.states[0].class = 'xyz-state1'; 
$scope.data.states[1].class = 'xyz-state2'; 
... 

Я сделал что-то подобное для другого (3-элементного) случая, за исключением случаев, когда я хотел изменить порядок элементов, я добавил свойство order для желаемого заказа в контроллере, а затем использовал data-ng-repeat="button in data.buttons|orderBy:'order'".

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