2

I am trying to change a progress bar content for each line in my table. To do so I used ng-init inside ng-repeat here is my code :

The view :

<tr ng-repeat-start="p in projetsListe" ng-init={{progressBar($index)}}>
  <td>
  <button class="btn btn-info btn-sm" ng-click="p.expanded = !p.expanded" expand data-toggle="collapse" id="{{p.IdProjet}}" data-target=".{{p.IdProjet}}">
  <span ng-bind="p.expanded ? '-' : '+'"></span>
  </button>
  </td>
  <td>{{p.NomProjet}}</td>
  <td>{{p.Responsable}}</td>
  <td>{{trestant[$index]}}</td>
  <td><div class="progress">
       <div class="progress-bar progress-bar-danger progress-bar-striped active" role="progressbar" aria-valuenow="40" id="pg1" aria-valuemin="0" aria-valuemax="100"><label id="l1"></label>
       </div>
       <div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="40" id="pg2" aria-valuemin="0" aria-valuemax="100"></div>
       </div>
       <label style="font-size :10px"><i class="fa fa-circle" style ="color : #df6d69"></i> Temps Passé : {{tpasse[$index]}}h</label>
                               &nbsp &nbsp
       <label style="font-size :10px"><i class="fa fa-circle" style ="color : green"></i> Temps Prévu : {{tprev[$index]}}h</label>
   </td>
</tr>

My function :

 $scope.progressBar= function(i){   
  var tpa;
        var p1 = document.getElementById('pg1');
        var p2 = document.getElementById('pg2');
        var l1 = document.getElementById('l1');
        tpa = ($scope.tpasse[i]*100)/$scope.tprev[i];
           if(tpa<=100){
             p1.style.width =  tpa + '%';
             p2.style.width =  100-tpa + '%';
             l1.innerHTML = " ";
           }
           else{
             p1.style.width = '100' +'%';   
             l1.innerHTML = "Attention : Temps prévu dépassé !";
           }  
 };

In the result I only get the data of the last line of the table and it appears in the first line:

enter image description here

This result should appear in the second line which is now empty, while the first one should have different result. Any suggestions on how to solve this issue ?

Here is a plunker that illustrates this problem : https://plnkr.co/edit/nGxqMOPejKMINb89Ewwx?p=preview

Jihane
  • 135
  • 12
  • can u show this in a plunker – Sa E Chowdary Jun 13 '17 at 09:47
  • You can't repeat element ID's in a page. Your whole approach is wrong. There should be no use of DOM code in controller. Can be done using `ng-style` and no need for `ng-init` , that is not what it is for – charlietfl Jun 13 '17 at 09:49
  • @charlietfl I am new to angular so I am using what I know so far, you mean ng-style can solve my problem ? – Jihane Jun 13 '17 at 09:52
  • 1
    You need to completely rethink how you coded things before when using angular. Strongly suggest reading : [Thinking in AngularJS if I have a jQuery background](https://stackoverflow.com/questions/14994391/thinking-in-angularjs-if-i-have-a-jquery-background) – charlietfl Jun 13 '17 at 09:55
  • @charlietfl thank you for the advice, but for now i need a solution to this particular case – Jihane Jun 13 '17 at 14:04
  • Suggest you study some angular tutorials – charlietfl Jun 13 '17 at 17:34
  • @SaEChowdary here is the link to a plunker : https://plnkr.co/edit/nGxqMOPejKMINb89Ewwx?p=preview – Jihane Jun 14 '17 at 07:42

2 Answers2

1

The main issue with you cod is that you have same id for different elements. And that is not allowed so only your progress bars are not coming properly. Below is the code that solves your problem. But what i would suggest is that there are other issues as well with your code for eg you are using interpolation with ng-init={{}progressBar($index)} but this will throw error as progressBar returns nothing. I think you need to review you code properly.

// Code goes here
var myApp = angular.module('myApp', []);

myApp.controller('Ctrl', function ($scope) {

$scope.tpasse = ['5049','26','100'];
$scope.tprev = ['688','336','400'];

$scope.projetsListe = [
    {
      "NomProjet" : "Project1",
      "ResponsableApitech" : "Jean"

    },

    {
     "NomProjet" : "Project2", 
     "ResponsableApitech" : "Edward"

    },

    {
     "NomProjet" : "Project2", 
     "ResponsableApitech" : "Edward"

    }
];
console.log($scope.projetsListe);

 $scope.progressBar= function(i){   
        var tpa;
        var p1 = document.getElementById('pg'+i);
        var p2 = document.getElementById('pgb'+i);
        var l1 = document.getElementById('l'+i);

        tpa = ($scope.tpasse[i]*100)/$scope.tprev[i];
           if(tpa<=100){
             p1.style.width =  tpa + '%';
             p2.style.width =  100-tpa + '%';
             l1.innerHTML = " ";
           }
           else{
             p1.style.width = '100' +'%';   
             l1.innerHTML = "Attention : You have reached the limits!";
           }  
 };
});

<html ng-app="myApp">

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
  <link data-require="bootstrap-css" data-semver="4.0.0-alpha.4" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" />
  <link data-require="bootstrap@*" data-semver="4.0.5" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" />
  <script data-require="jquery" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script data-require="bootstrap" data-semver="4.0.5" src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
  <link href="style.css" rel="stylesheet" />
  <script src="script.js"></script>
</head>

<body>
  <div ng-controller="Ctrl">

    <table class="table table-bordered table-hover table-striped">
      <thead>
        <tr>
          <th>Nom</th>
          <th>Responsable</th>
          <th>Progress</th>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="p in projetsListe track by $index">
          <td>{{p.NomProjet}}</td>
          <td>{{p.ResponsableApitech}}</td>
          <td>
            <div class="progress" ng-init="{{progressBar($index)}}">
              <div class="progress-bar progress-bar-danger " role="progressbar" aria-valuenow="40" id="pg{{$index}}" aria-valuemin="0" aria-valuemax="100">
                <label id="l{{$index}}"></label>
              </div>
              <div class="progress-bar progress-bar-success progress-bar-striped " role="progressbar" aria-valuenow="40" id="pgb{{$index}}" aria-valuemin="0" aria-valuemax="100"></div>
            </div>
            <label style="font-size :10px"><i class="fa fa-circle" style="color : #df6d69"></i> Temps Passé : {{tpasse[$index]}}h</label> &nbsp; &nbsp;
            <label style="font-size :10px"><i class="fa fa-circle" style="color : green"></i> Temps Prévu : {{tprev[$index]}}h</label>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</body>

</html>

Updated Plunker

Hope it helps :)

Manish
  • 4,692
  • 3
  • 29
  • 41
  • Thank you very much, this works perfectly you literally saved me, I will indeed review my code to avoid these issues – Jihane Jun 14 '17 at 08:47
1

I know, you've already accepted the answer, but I still want to suggest you to use components approach (because you are using angularjs 1.5+) to solve your problem. There a few things in your code that looks not very good: ngInit adds unnecessary amounts of logic into your templates and you can avoid using it because components have a well-defined lifecycle and you can use $onChanges hook to re-draw your progress bar. Also manipulating DOM inside the controller is not an angular-way of working with your views, it is better to use ngStyle directive in your case. Here is a working example:

angular.module('myApp', []).controller('Ctrl', function ($scope) {
 $scope.projetsListe = [
    {
      NomProjet : "Project1",
      ResponsableApitech : "Jean",
      tpasse: 5049,
      tprev: 688
    }, {
      NomProjet : "Project2", 
      ResponsableApitech : "Edward",
      tpasse: 26,
      tprev: 336
    }, {
      NomProjet : "Project4", 
      ResponsableApitech : "Edward",
      tpasse: 177,
      tprev: 336
    }
  ];
})
.component('progressBar', {
  templateUrl: "progress-bar.html",
  bindings: {
    project: '<'
  },
  controller: 'ProgressBarCtrl'
})
.controller('ProgressBarCtrl', [function ProgressBarCtrl (){
  var ctrl = this;
  
  ctrl.$onChanges = onChanges;

  ctrl.styles = {};
  
  function onChanges(changesObject){
    ctrl.styles = getStyles(ctrl.project);
  }
  
  function getStyles(project){
      var tpa, styles = {};
      tpa = (project.tpasse*100) / project.tprev;
 
      if (tpa <= 100){
        styles = {
          p1Width: tpa + '%',
          p2Width: 100-tpa + '%',
          l1innerHTML: " "
        };
      } else{
        styles = {
          p1Width: '100%',
          l1innerHTML: "Attention : You have reached the limits!"
        };
      } 
      
     return styles;
  }
  
  return ctrl;
  
}]);
<html ng-app="myApp">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
  <link data-require="bootstrap-css" data-semver="4.0.0-alpha.4" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" />
  <link data-require="bootstrap@*" data-semver="4.0.5" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" />
  <script data-require="jquery" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script src="https://npmcdn.com/tether@1.2.4/dist/js/tether.min.js"></script>
  <script data-require="bootstrap" data-semver="4.0.5" src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
</head>

<body>
  <div ng-controller="Ctrl">
  
  <table class="table table-bordered table-hover table-striped">
     <thead>
      <tr>
        <th>Name</th>
        <th>Responsable</th>
        <th>Progress</th>
      </tr>
    </thead>
    <tbody>
     <tr ng-repeat="p in projetsListe">
       <td>{{p.NomProjet}}</td>
       <td>{{p.ResponsableApitech}}</td>
       <td>
         <progress-bar project="p"></progress-bar>
       </td>
      </tr>
    </tbody>
  </table>

<script type="text/ng-template" id="progress-bar.html">
<div class="progress">
    <div class="progress-bar progress-bar-danger" ng-style="{'width': $ctrl.styles.p1Width}" role="progressbar"
         aria-valuenow="40" aria-valuemin="0"
         aria-valuemax="100">
        <label>{{$ctrl.styles.l1innerHTML}}</label>
    </div>
    <div class="progress-bar progress-bar-success progress-bar-striped" ng-style="{'width': $ctrl.styles.p2Width}"
         role="progressbar" aria-valuenow="40"
         aria-valuemin="0" aria-valuemax="100"></div>
</div>

<label style="font-size :10px"><i class="fa fa-circle" style="color : #df6d69"></i> The actual Time spent :
    {{$ctrl.project.tpasse}}h</label>
&nbsp; &nbsp;
<label style="font-size :10px"><i class="fa fa-circle" style="color : green"></i> The Initial expected time :
    {{$ctrl.project.tprev}}h</label>
</script>

</div>
</body>
</html>
Stanislav Kvitash
  • 4,614
  • 18
  • 29
  • This sure is a more proper way to do it, and it helped me understand the `ngStyle` directive logic, Thank you very much – Jihane Jun 14 '17 at 09:49