我有一个模板,其中包含(部分)完全相同的内容重复两次或三次,并对绑定进行微小更改,例如:
<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的东西,但由于以下原因我无法使用它:
我设法在一个单独的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 :(得分:2)
这几乎是自定义指令的教科书案例。定义一个指令,然后你可以做
<state ng-repeat="item in data.states" item="item">.
或者,如果自定义指令太过分(取决于您是否会在其他地方重复使用该视图组件),您可以在整个div上添加ng-repeat。唯一真正的问题是class =&#34; xyz-stateN&#34;东西,但我打赌你可以用ng级用法来解决这个问题。
编辑:
如果你进行ng-repeat,你可以只使用$ index键(只要你总是从零开始计数,并且状态类与索引相同)。像
这样的东西<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>
可能会正常工作。总而言之,在我看来,几乎总是值得做出指示。代码一直在循环使用,另外,如果这让你感到紧张,你可以对命名空间和模块化保持谨慎。
答案 1 :(得分: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="" ...>
,那么不会工作,尽管文档说这应该也有效。我假设这里有某种验证的东西在干扰。
答案 2 :(得分: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类)已泄漏到控制器中,但我认为代码清晰度的好处超过了这一点。