Prasad BGLV
Prasad BGLV

Reputation: 11

Angular js I am not able to call my buttons dynamically

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

Answers (4)

jdforsythe
jdforsythe

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

Steen
Steen

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

Nishanth Matha
Nishanth Matha

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

Dmitriy
Dmitriy

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

Related Questions