我正在对编译链接编译中的其他指令的指令进行测试,我的问题是我无法弄清楚如何将数据传递到编译的指令范围,也许它应该通过属性或通过范围,但我不能实现这一目标。
我有指令A
,其内容是翻译,内容是另一个指令B
,指令A
将解析数据并克隆多个B
指令,具体取决于数据的长度,对于每个数据,应该有一个B
指令,其中包含从迭代中收集的数据,使每个B
在A
指令内成为唯一的指令。
所以这是代码:
HTML:
<body ng-app="app" ng-controller="testController">
<grid rows="3" collection="blogs">
<blog></blog>
</grid>
</body>
使用Javascript:
var app = angular.module("app", []);
app.controller("testController", function($scope) {
$scope.blogs = [{
id: 1,
title: "Blog #1",
author: "Random user"
}, {
id: 2,
title: "Blog #2",
author: "Random user"
}, {
id: 3,
title: "Blog #3",
author: "Random user"
}, {
id: 4,
title: "Blog #4",
author: "Random user"
}, {
id: 5,
title: "Blog #5",
author: "Random user"
}, {
id: 6,
title: "Blog #6",
author: "Random user"
}, {
id: 7,
title: "Blog #7",
author: "Random user"
}, {
id: 8,
title: "Blog #8",
author: "Random user"
}, {
id: 9,
title: "Blog #9",
author: "Random user"
}];
});
app.directive("blog", function() {
return {
restrict: "E",
template: blogTemplate,
replace: true,
scope: {
data: "@reference"
},
controller: controller
};
function controller($scope) {
$scope.access = function() {
console.log($scope);
}
}
});
app.directive("grid", function($compile) {
return {
restrict: "E",
transclude: true,
scope: {
columns: "@rows",
collection: "=?"
},
link: link
};
function link(scope, element, attr, ctrl, transclude) {
var _columnLength;
var _columnTrack = 0;
var columns = [];
_columnLength = parseInt(scope.columns);
// Create columns from row's attribute
for (i = 0; i < _columnLength; i++) {
var column = angular.element(document.createElement("div"));
column.addClass("grid-column");
columns.push(column);
}
// Fill all columns with the passed collection scope
fillColumns();
// Render all columns in the DOM
renderColumns(element, columns);
function renderColumns(el, columns) {
for (let col of columns) {
el.append(col);
}
}
function fillColumns() {
var collection = scope.collection;
// Compile multiple transcluded content for each collection item
for (let data of collection) {
transclude(scope.$new(), function(clone, innerScope) {
// Set this property to test if the compiled directive recieves it
innerScope.test = _columnTrack;
$compile(clone)(innerScope);
// Append the compiled clone into its respective column
appendColumn(clone);
});
}
}
function appendColumn(data) {
columns[_columnTrack].append(data);
if (_columnTrack < (_columnLength - 1)) {
_columnTrack++;
} else {
_columnTrack = 0;
}
}
}
});
我希望创建的范围是在网格链接编译中。如果需要运行时示例,则此处为codepen,注意:codepen具有博客模板的变量,因此您可以看到它的结构
答案 0 :(得分:1)
您需要在子指令上使用隔离范围,以便传入数据。这可以通过在编译之前添加属性来完成。一个大问题是转换是在for循环中,导致编译的元素被transclude重新编译并且范围丢失。
这应该做一次,这样就可以获得指令(网格)内的模板。然后可以使用该模板克隆具有data属性的副本。
var blogTemplate = `
<div class="blog-preview">
<div class="blog-thumbnail"></div>
<div class="blog-wrapper">
<div class="blog-head">
<h2 class="blog-title">{{data.id}}</h2>
<p class="blog-author">{{data.author}}r</p>
<p class="blog-date">2017-03-06</p>
</div>
<div class="blog-actions">
</div>
<div class="blog-content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
<button href="#" class="blog-access" ng-click="access()">access</button>
</div>
</div>
</div>
`;
var app = angular.module("app", []);
app.controller("testController", function($scope) {
$scope.blogs = [
{
id: 1,
title: "Blog #1",
author: "Random user"
},
{
id: 2,
title: "Blog #2",
author: "Random user"
},
{
id: 3,
title: "Blog #3",
author: "Random user"
},
{
id: 4,
title: "Blog #4",
author: "Random user"
},
{
id: 5,
title: "Blog #5",
author: "Random user"
},
{
id: 6,
title: "Blog #6",
author: "Random user"
},
{
id: 7,
title: "Blog #7",
author: "Random user"
},
{
id: 8,
title: "Blog #8",
author: "Random user"
},
{
id: 9,
title: "Blog #9",
author: "Random user"
}
];
});
app.directive("blog", function() {
return {
restrict: "E",
template: blogTemplate,
replace: false,
scope: {
data: "=data"
},
link: link
};
function link($scope) {
$scope.access = function() {
console.log($scope.data);
};
}
});
app.directive("grid", function($compile) {
return {
restrict: "E",
transclude: true,
scope: {
columns: "@rows",
collection: "=?"
},
link: link
};
function link(scope, element, attr, ctrl, transclude) {
var _columnLength;
var _columnTrack = 0;
var columns = [];
_columnLength = parseInt(scope.columns);
// Create columns from row's attribute
for (i = 0; i < _columnLength; i++) {
var column = angular.element(document.createElement("div"));
column.addClass("grid-column");
columns.push(column);
}
// Fill all columns with the passed collection scope
fillColumns();
// Render all columns in the DOM
renderColumns(element, columns);
function renderColumns(el, columns) {
for (let col of columns) {
el.append(col);
}
}
function fillColumns() {
var collection = scope.collection;
// Compile multiple transcluded content for each collection item
var idx = 0;
var template;
// fetch template
transclude(scope, function(clone, innerScope, element) {
template = clone;
innerScope = innerScope;
});
for (let data of collection) {
var dataAttr = `collection[${idx++}]`;
var item = template.clone();
item.attr("data", dataAttr);
$compile(item)(scope);
// Append the compiled clone into its respective column
appendColumn(item);
}
}
function appendColumn(data) {
columns[_columnTrack].append(data);
if (_columnTrack < _columnLength - 1) {
_columnTrack++;
} else {
_columnTrack = 0;
}
}
}
});
* {
font-family: "Raleway", sans-serif;
}
body {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: stretch;
align-content: stretch;
}
grid {
display: flex;
}
.blog-preview {
width: 280px;
margin: 15px 15px 60px;
display: flex;
flex-direction: column;
}
.blog-preview > .blog-thumbnail {
width: 100%;
height: 190px;
background: #181D20;
}
.blog-preview > .blog-wrapper {
display: flex;
flex-direction: column;
}
.blog-preview > .blog-wrapper > .blog-head {
height: 55px;
margin: 6px 8px;
}
.blog-preview > .blog-wrapper > .blog-head > .blog-title {
margin: 2px 0 0 0;
}
.blog-preview > .blog-wrapper > .blog-head > p {
font-size: 10px;
margin: 0 0 3px 0;
}
.blog-preview > .blog-wrapper > .blog-actions {
height: 16px;
background: rgba(24, 29, 32, 0.5);
}
.blog-preview > .blog-wrapper > .blog-content {
display: flex;
flex-direction: column;
}
.blog-preview > .blog-wrapper > .blog-content p {
margin: 16px 10px;
}
.blog-preview > .blog-wrapper > .blog-content > .blog-access {
text-decoration: none;
text-align: center;
vertical-align: middle;
width: 100px;
height: 25px;
line-height: 25px;
margin: auto;
color: #FFF;
background: #3E515A;
}
<body ng-app="app" ng-controller="testController">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
<grid rows="3" collection="blogs">
<blog></blog>
</grid>
</body>
答案 1 :(得分:0)
我已经做了一个解决方法,我不认为它实际上是一个很好的方法,但至少得到它我正在寻找的方式..我将把它作为临时方法。
所以我在这个transclude函数中的解决方法是这样的:
function fillColumns(){
var collection = scope.collection;
// Compile multiple transcluded content for each collection item
for(let data of collection){
transclude(scope.$new(), function(clone, innerScope){
// Set this property to test if the compiled directive recieves it
innerScope.data = data; //This is what has changed
$compile(clone)(innerScope);
// Append the compiled clone into its respective column
appendColumn(clone);
});
}
}
然后使用$scope.$parent.data
function controller($scope){
$scope.data = $scope.$parent.data;
}