在每个内部基于代码的转换对最终元素不起作用

时间:2016-12-02 19:18:56

标签: angularjs

this example中,我在ng-each内有一个被转换的指令。它似乎只包括最后一次通过每个的转换!

var app = angular.module('testApp', []);

app.directive ('labeledElement', [
() => {
	const link = ($scope, $el, attrs, _0, transclude) => {
		$scope.label = attrs.label;
		$el.find('label').prepend(transclude());
	}
	return {
		restrict: 'E',
		link,
		scope: {
			label: '@',
		},
		transclude: true,
		template: `
<label>
	<span class="label">{{label}}</span>
</label>
`,
	}
}])

app
.controller('TopLevel',
	function() {
		this.sources = [
			{ domain:"first item"},
			{ domain:"second item"},
			{ domain:"third item"},
		]
	})

angular.bootstrap (document.querySelector('body'), ['testApp'])
<body ng-controller="TopLevel as $ctrl">
    <style>
      input:invalid+.label {
        color: red;
      }
    </style>
  <p>Why on earth does only the last input display?</p>
	<section class="admin-integration-sources">
		<div>
			<ul class="configured-sources-list">
				<li ng-repeat="source in $ctrl.sources">
					<labeled-element label="A Label">
						<input ng-model="source.domain" required />
					</labeled-element>
				</li>
			</ul>
		</div>
	</section>
</body>

    <script data-require="angular.js@1.5.x" src="https://code.angularjs.org/1.5.8/angular.js" data-semver="1.5.8"></script>

需要注意的一些事项

  • 如果我在模板中使用<ng-transclude>,那么事情就是,但是中间<ng-transclude>元素的创建打破了我input:invalid+.label的css模式考虑我的应用程序 html如何工作的基础。
  • ng-transclude作为属性也可以,但会消灭我的span.label
  • 这肯定与ng-each有关。如果我手动创建三个li元素并将它们链接到$ctrl.sources[0]$ctrl.sources[1]等,它就可以正常使用了!

发生了什么事?!

1 个答案:

答案 0 :(得分:1)

Transclusion并非旨在以这种方式工作。您在同一范围内发生了两次转换,&lt; li&gt;和&lt; labeled-element&gt;,这是&lt; body&gt;。

的范围

基本上,ng-repeat的每次迭代都是在先前的&lt; labeled-element&gt;上进行的。转换,这就是为什么只有最后的&lt; labeled-element&gt;出现了翻译。

Here's an expert explanation of the issue

解决方案是使用compile来根据需要修复标记。

app.directive('labeledElement', function () {
    return {
        restrict: "E",
        compile: function (element, attr) {
            let template = angular.element('<label><span class="label">' + element.attr('label') + '</span></label>');
            // Extract the children from this instance of the directive
            let children = element.contents();
            // Wrap the children in our template
            let injectElement = template.find('inject');
            injectElement.replaceWith(children);
            // Append this new template to our compile element
            element.append(template);
        }
    }
});

以下是plunkr使用编译重现您的问题和解决方法。