Reputation: 11
i need ur help figuring out this problem... im new to angular just started playing on ground.
Initially i have only one button on load "Add list", with add list user can able to add multiple lists with itself have a button("Add Phase") for each list, on click of Add phase it should show the content related to that phase.
Im doing this all in dynamic way.
My HTML looks like:
<button ng-click="list()">add list</button>
<div id="container"></div>
My controller looks like:
$scope.list =function(){
var name1html = '<div id="ide"><button ng-click="phase()">Add Phase</button><div id="drop"></div></div>';
var name1 = $compile(name1html)($scope);
angular.element(document.getElementById('container')).append(name1);
}
$scope.phase =function(){
var name2html = '<div>123</div>';
var name2 = $compile(name2html)($scope);
angular.element(document.getElementById('drop')).append(name2);
}
Actual Output: On click of 2nd Add phase button it is again adding to 1st button
Expected Output: Im expecting something like this
Upvotes: 0
Views: 114
Reputation: 1067
I think you're not thinking about things the Angular way. You don't really need all those $compile
and the HTML in your JS. Let Angular do the heavy lifting. Use an array of lists in your controller and iterate over it in the markup with ng-repeat. You can nest an inner ng-repeat for the phases inside each list. Something like this:
<button ng-click="addList()">Add list</button>
<div>
<div ng-repeat="list in lists track by $index">
<div>
<button ng-click="addPhase($index)">Add Phase</button>
<ul>
<li ng-repeat="phase in list.phases track by $index">
{{ phase }}
</li>
</ul>
</div>
</div>
</div>
And in your controller:
$scope.lists = [];
$scope.addList = function() {
$scope.lists.push({ phases: [] });
};
$scope.addPhase = function($index) {
$scope.lists[$index].phases.push('123');
};
And for good measure, here's a working Plunker
Note: I removed the ids from the tags, because you don't need them for Angular (it keeps track of them internally) but if you really needed them you could use the $index
to add a numerical value to them (to @DmitriyLoskutov point, id attributes are meant to be unique, whereas you were trying to add multiple elements with the same id value).
Edit:
You can put anything inside the phases. Like this:
<button ng-click="addList()">Add list</button>
<div>
<div ng-repeat="list in lists track by $index">
<div>
<button ng-click="addPhase($index)">Add Phase</button>
<ul>
<li ng-repeat="phase in list.phases track by $index">
<div data-exp-page exp-page-attribute-one="{{$index}}" exp-page-attribute-two="{{phase.name}}"></div>
</li>
</ul>
</div>
</div>
</div>
This is just to show that you can include any HTML inside that phase <li>
. If you need to pass attributes on the directive, you can do so. The uniqueness is defined by the track by
value. This can be $index
in the example, since there is no existing model with any unique value, or if you have an existing model with a unique property (database records, for instance) you can change $index
to list.uuid
or whatever.
You can also access the list from within the phase by using $parent.$index
- if you want to remove a phase that was added, for instance, you could do the following:
<li ng-repeat="phase in list.phases track by $index">
<div>
<input type="text" name="phase-name-{{$index}}" ng-model="phase.name">
<button type="button" ng-click="removePhase($parent.$index, $index)">Remove this phase</button>
</div>
</li>
And then in the controller:
$scope.removePhase = function($listIndex, $phaseIndex) {
$scope.lists[$listIndex].phases.splice($phaseIndex, 1);
};
Upvotes: 1
Reputation: 2877
using the repeats as "templates" - notice the textarea which reflects the items in the list:
http://jsfiddle.net/0088orkk/1/
The object generated by the "user created list" and entered values can be sent, stored or manipulated quite easily.
<div ng-app ng-controller="MyCtrl">
<input type="button" value="addList" ng-click="addList()"/><br/><br/>
<ul>
<li ng-repeat="item in items"> <input type="button" value="addPhase" ng-click="addPhase(item)"/>
<div ng-repeat="phase in item.phases">
{{phase.value}}
<form>
<input type="text" ng-model="phase.Value1"/>
<input type="text" ng-model="phase.Value2"/>
<input type="text" ng-model="phase.Value3"/>
</form>
</div>
</li>
</ul><br/>
<br/>
<hr/>
<br/>
Items:<br/>
<textarea style="width:400px;height:400px">{{items}}</textarea>
</div>
function MyCtrl($scope) {
$scope.items =[];
$scope.addList = function(){
$scope.items.push({phases:[]});
};
$scope.addPhase = function(item){
item.phases.push({value:123});
};
}
Upvotes: 0
Reputation: 6081
try
$scope.list =function(){
var name1html = '<div id="ide"><button ng-click="phase($event)">Add Phase</button><div id="drop"></div></div>';
var name1 = $compile(name1html)($scope);
angular.element(document.getElementById('container')).append(name1);
}
$scope.phase =function($event){
var name2html = '<div>123</div>';
var name2 = $compile(name2html)($scope);
angular.element($event.currentTarget).next().append(name2);
}
and also remove your id
as it being duplicated whenever phase
is triggered
Upvotes: 0
Reputation: 3765
$scope.list =function() {
// use class insead of id
var name1html = '<div class="ide"><button ng-click="phase($event)">Add Phase</button><div class="drop"></div></div>';
var name1 = $compile(name1html)($scope);
angular.element(document.getElementById('container')).append(name1);
};
$scope.phase = function ($event) {
var name2html = '<div>123</div>';
var name2 = $compile(name2html)($scope);
var drop = $event.target.parentNode.querySelector('.drop'); // we get the right div tag with class drop
angular.element(drop).append(name2);
};
Upvotes: 0