I would like to add some Angular-enabled DOM elements programmatically. Actually, I probably will need to add custom components. How can I do it?
Here's a trivial fiddle to demonstrate the issue: /
HTML:
<div ng-app="main">
<div ng-controller="MyCtrl">
<button ng-click="add()" >Add</button>
<div id="container">
<div>{{test}}</div>
</div>
</div>
</div>
JS:
angular.module("main", []).controller("MyCtrl", function($scope) {
$scope.add = function() {
$("#container").append("<div>{{test}}</div>");
};
$scope.test = 'Test Message';
});
Just in case, I expect it to add a div showing "Test Message" for each click - not {{test}}.
Why do I need it? Well, I would like to have a few sortable columns (in jQuery sortable sense) with portlets. I imagine each portlet could be a component.
Am I climbing the wrong hill? What is the Angular way to solve this?
EDIT: I hoped this simplistic example wouldn't end that way, but anyway. The ultimate goal is not to display a div for each element in an array.
What I really want is a more complex controller. I need a portlet container with some interesting behavior. It may need to decide to place each portlet in a different column. It may offer changing the layout and have a decent way to reorganize portlets in such event. And so on.
I would like to add some Angular-enabled DOM elements programmatically. Actually, I probably will need to add custom components. How can I do it?
Here's a trivial fiddle to demonstrate the issue: http://jsfiddle.net/ZJSz4/2/
HTML:
<div ng-app="main">
<div ng-controller="MyCtrl">
<button ng-click="add()" >Add</button>
<div id="container">
<div>{{test}}</div>
</div>
</div>
</div>
JS:
angular.module("main", []).controller("MyCtrl", function($scope) {
$scope.add = function() {
$("#container").append("<div>{{test}}</div>");
};
$scope.test = 'Test Message';
});
Just in case, I expect it to add a div showing "Test Message" for each click - not {{test}}.
Why do I need it? Well, I would like to have a few sortable columns (in jQuery sortable sense) with portlets. I imagine each portlet could be a component.
Am I climbing the wrong hill? What is the Angular way to solve this?
EDIT: I hoped this simplistic example wouldn't end that way, but anyway. The ultimate goal is not to display a div for each element in an array.
What I really want is a more complex controller. I need a portlet container with some interesting behavior. It may need to decide to place each portlet in a different column. It may offer changing the layout and have a decent way to reorganize portlets in such event. And so on.
Share Improve this question edited Apr 5, 2013 at 20:14 Konrad Garus asked Apr 5, 2013 at 20:05 Konrad GarusKonrad Garus 54k44 gold badges161 silver badges233 bronze badges 1- did you go through the tutorial in the docs online ? you should do that first. You need to let your model drive the UI. if you need more "tests" , create an array of tests and add/remove elements. the view will update automatically. – mpm Commented Apr 5, 2013 at 20:09
3 Answers
Reset to default 8Although I am not entirely sure what the desired outcome is, you do want to be sure that all DOM manipulation is done within a directive and not inside your controller.
This JSfiddle example should get you going in the right direction.
http://jsfiddle.net/ZJSz4/5/
<div ng-app="main">
<div ng-controller="MyCtrl">
<div id="container">
<button ng-click="add()" >Add</button>
<ng-portlet></ng-portlet>
</div>
</div>
angular.module("main", []).controller("MyCtrl", function($scope) {
$scope.test = 'Test Message';
}).directive("ngPortlet", function ($compile) {
return {
template: '<div>{{test}}</div> ',
restrict: 'E',
link: function (scope, elm) {
scope.add = function(){
console.log(elm);
elm.after($compile('<ng-portlet></ng-portlet>')(scope));
}
}
};
});
If you want multiple tests, I'd suggest setting it up like so.
<div ng-app="main">
<div ng-controller="MyCtrl">
<button ng-click="add()" >Add</button>
<div id="container">
<div ng-repeat="test in tests">{{test.name}}</div>
</div>
</div>
</div>
$scope.tests = []; // define this as an array
$scope.add = function() {
var newTest = {name: 'Test Message'};
$scope.tests.push(newTest);
};
This will dynamically create divs based on your tests object.
As @Christopher Marshall pointed out, the simplest way to do this is using a repeating element and pushing a new item into scope on the button press.
[HTML]
<div ng-app="main">
<div ng-controller="MyCtrl">
<button ng-click="add()" >Add</button>
<div id="container">
<div ng-repeat="test in tests">{{test}}</div>
</div>
</div>
</div>
[JS]
angular.module("main", []).controller("MyCtrl", function($scope) {
$scope.add = function() {
$scope.tests.push('New Message');
};
$scope.tests = ["Test Message","Test Message 2"];
});