I want to define a directive which will show the first child which contains a button at first. If we click on the button, the second child will be replace the first one.
我想定义一个指令,它将首先显示包含按钮的第一个子节点。如果我们点击按钮,第二个孩子将替换第一个孩子。
HTML:
HTML:
<div show-more>
<div>short <button ng-click="showMore()">click-me to show more</button></div>
<div>full</div>
</div>
Angular:
角度:
angular.module("app", [])
.directive("showMore", function() {
return {
restrict: 'A',
scope: {},
link: function(scope, element, attrs) {
var children = element.children();
var short = children[0];
var full = children[1];
element.empty().append(short);
scope.showMore = function() {
element.empty().append(full);
};
}
};
});
The problem is that when I click the button, there is nothing happen. I tried a lot but still not work.
问题是当我点击按钮时,没有任何事情发生。我尝试了很多但仍然无法工作。
You can see a live demo here: http://jsbin.com/rugov/2/edit
你可以在这里看到现场演示:http://jsbin.com/rugov/2/edit
How to fix it?
怎么解决?
3 个解决方案
#1
1
Since you are changing the DOM of the element
of your directive, you will need to re-$compile
the element, like this:
由于您要更改指令元素的DOM,因此需要重新编译元素,如下所示:
.directive("showMore", function($compile) {
return {
restrict: 'A',
scope: {},
link: function(scope, element, attrs) {
var children = element.children();
var short = children[0];
var full = children[1];
element.empty().append(short);
$compile(element.contents())(scope);
scope.showMore = function() {
element.empty().append(full);
};
}
};
});
Working Example
#2
1
The problem is that your directive creates new isolated scope, but ng-click directive is placed on element, that is in another scope. I would implement your requirements via 2 directive, one depends from another.
问题是你的指令创建了新的隔离范围,但是ng-click指令放在元素上,即另一个范围内。我将通过2指令实现您的要求,一个取决于另一个。
angular.module("app", [])
.directive("showMoreWrapper", function() {
return {
restrict: 'A',
scope: {},
controller: function($element) {
this.showMore = function() {
var children = $element.children();
children.eq(0).hide();
children.eq(1).show();
};
},
link: function(scope, element, attrs) {
var children = element.children();
children.eq(1).hide();
}
};
})
.directive("showMore", function() {
return {
restrict: 'A',
require: '^showMoreWrapper',
link: function(scope, element, attrs, showMoreWrapper) {
element.on('click', showMoreWrapper.showMore);
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div show-more-wrapper>
<div>short
<button show-more>click-me to show more</button>
</div>
<div>full</div>
</div>
</div>
#3
0
I would take a custom component approach
我会采用自定义组件方法
angular.module("app", [])
.directive("showMore", function() {
return {
restrict: 'E',
scope: {},
transclude: true,
template: '<button ng-click="toggle()">{{title}}</button><div ng-transclude></div>',
controller: function($scope) {
var self = this;
$scope.title = "Show More";
$scope.toggle = function() {
self.short.show = !self.short.show;
self.full.show = !self.full.show;
$scope.title = self.short.show ? "Show More" : "Show Less";
};
this.addShort = function(short) {
self.short = short;
};
this.addFull = function(full) {
self.full = full;
};
}
};
})
.directive("short", function() {
return {
restrict: 'E',
scope: {},
require: '^showMore',
transclude: true,
template: '<div ng-if="show" ng-transclude></div>',
link: function(scope, element, attrs, showMoreCtrl) {
scope.show = true;
showMoreCtrl.addShort(scope);
}
};
})
.directive("full", function() {
return {
restrict: 'E',
scope: {},
require: '^showMore',
transclude: true,
template: '<div ng-if="show" ng-transclude></div>',
link: function(scope, element, attrs, showMoreCtrl) {
scope.show = false;
showMoreCtrl.addFull(scope);
}
};
});
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<div ng-app="app">
<show-more>
<short>short</short>
<full>full</full>
</show-more>
</div>
#1
1
Since you are changing the DOM of the element
of your directive, you will need to re-$compile
the element, like this:
由于您要更改指令元素的DOM,因此需要重新编译元素,如下所示:
.directive("showMore", function($compile) {
return {
restrict: 'A',
scope: {},
link: function(scope, element, attrs) {
var children = element.children();
var short = children[0];
var full = children[1];
element.empty().append(short);
$compile(element.contents())(scope);
scope.showMore = function() {
element.empty().append(full);
};
}
};
});
Working Example
#2
1
The problem is that your directive creates new isolated scope, but ng-click directive is placed on element, that is in another scope. I would implement your requirements via 2 directive, one depends from another.
问题是你的指令创建了新的隔离范围,但是ng-click指令放在元素上,即另一个范围内。我将通过2指令实现您的要求,一个取决于另一个。
angular.module("app", [])
.directive("showMoreWrapper", function() {
return {
restrict: 'A',
scope: {},
controller: function($element) {
this.showMore = function() {
var children = $element.children();
children.eq(0).hide();
children.eq(1).show();
};
},
link: function(scope, element, attrs) {
var children = element.children();
children.eq(1).hide();
}
};
})
.directive("showMore", function() {
return {
restrict: 'A',
require: '^showMoreWrapper',
link: function(scope, element, attrs, showMoreWrapper) {
element.on('click', showMoreWrapper.showMore);
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div show-more-wrapper>
<div>short
<button show-more>click-me to show more</button>
</div>
<div>full</div>
</div>
</div>
#3
0
I would take a custom component approach
我会采用自定义组件方法
angular.module("app", [])
.directive("showMore", function() {
return {
restrict: 'E',
scope: {},
transclude: true,
template: '<button ng-click="toggle()">{{title}}</button><div ng-transclude></div>',
controller: function($scope) {
var self = this;
$scope.title = "Show More";
$scope.toggle = function() {
self.short.show = !self.short.show;
self.full.show = !self.full.show;
$scope.title = self.short.show ? "Show More" : "Show Less";
};
this.addShort = function(short) {
self.short = short;
};
this.addFull = function(full) {
self.full = full;
};
}
};
})
.directive("short", function() {
return {
restrict: 'E',
scope: {},
require: '^showMore',
transclude: true,
template: '<div ng-if="show" ng-transclude></div>',
link: function(scope, element, attrs, showMoreCtrl) {
scope.show = true;
showMoreCtrl.addShort(scope);
}
};
})
.directive("full", function() {
return {
restrict: 'E',
scope: {},
require: '^showMore',
transclude: true,
template: '<div ng-if="show" ng-transclude></div>',
link: function(scope, element, attrs, showMoreCtrl) {
scope.show = false;
showMoreCtrl.addFull(scope);
}
};
});
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<div ng-app="app">
<show-more>
<short>short</short>
<full>full</full>
</show-more>
</div>