1

I'm transitioning from NGJS to NG and trying to recode my previous application to practice.

I stumbled upon the new NgInit where initializations are done in Angular's Component.

What I'm trying to achieve is to initialize a value WITHIN the scope to be used as a toggle to hide and unhide HTML elements. I'm trying to solve this without looping within ngOnInit() {} to initialize for each object within the array. (See ng-init in ng-repeat block)

Below is a working copy of the scenario I'm trying to achieve:

angular.module("app", [])

.controller("controller", function($scope) {
  
  $scope.init = function() {
    $scope.modules = [
      {
        label: 'Module A',
        children: [
          'Module A - 1',
          'Module A - 2',
          'Module A - 3'
        ]
      },
      {
        label: 'Module B',
        children: [
          'Module B - 1',
          'Module B - 2',
          'Module B - 3'
        ]
      },
      {
        label: 'Module C',
        children: [
          'Module C - 1',
          'Module C - 2',
          'Module C - 3'
        ]
      }
    ];
  };
  
});
.child {
  padding-left: 24px;
  padding-top: 8px;
  padding-bottom: 8px;
}

.parent {
  padding: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="app" ng-controller="controller" ng-init="init()">
  <div class="parent" ng-repeat="module in modules" ng-init="toggle=true">
    {{module.label}}
    <button ng-click="toggle = !toggle">toggle</button>
    <span ng-if="toggle" id="child-group">
      <div class="child" ng-repeat="child in module.children">
        {{child}}
      </div>
    </span>
  </div>
</body>

Here's a Plunker if you prefer: https://plnkr.co/edit/JDBBPLkr21wxSe2dlRBv?p=preview

3
  • You can "initialize" a variable, when you defined it, in constructor, or in ngOnInit function (your component must be implements OnInit). Generally is recomended make in ngOnInit Commented Mar 22, 2018 at 8:01
  • Yeah. But unfortunately, NgOnInit behaves differently from the previous ng-init. The initialized toggle is accessible only within the scope of initialization. Another thing is if I initialized the toggle in constructor, I have to define 1 boolean for each Parent which you don't want to do specially if you don't have any idea how many "modules" (in this case) the API gateway will respond. Commented Mar 22, 2018 at 8:07
  • In Angular js (as I remember it) $scope is "only". In Angular, if you want to mantein the value of a "variable" along the app life, you must use a "service" to save the variable, see, e.g. stackoverflow.com/questions/34572005/… Commented Mar 22, 2018 at 8:13

3 Answers 3

3

You could do it like this. You loop over your array with *ngFor. The button toggles the corresponding boolean value, which defines if your element is shown or not (with the *ngIf directive)

@Component({
     selector: 'my-app',
     template: `
         <div *ngFor="let module of modules; let i = index">
         <button (click)="show[i] = !show[i]">toggle</button>
         <h2>{{module.label}}</h2>
         <div *ngIf="show[i]">
            <li *ngFor="let child of module.children">
             {{child}}
          </li>
         </div>
         </div>             
    `,
})

Then initialize your variables:

export class AppComponent {     
  modules:any[];
  show:boolean[];

  constructor() {
    this.modules = [
    {
       label: 'Module A',
       children: [
      'Module A - 1',
      'Module A - 2',
      'Module A - 3'
    ]
    },
    {
      label: 'Module B',
      children: [
      'Module B - 1',
      'Module B - 2',
      'Module B - 3'
    ]
    },
    {
      label: 'Module C',
      children: [
      'Module C - 1',
      'Module C - 2',
      'Module C - 3'
    ]
    }
    ];
      this.show = this.modules.map(()=>true);
   }
 }
Sign up to request clarification or add additional context in comments.

1 Comment

Hey Opp! Thanks! Had my navigation work as expected with this solution
2

Implement OnInit while declaring the component's class and move your initialization code to ngOnInit function.

@Component({
  ...
})
export class componentClass implements OnInit {
  ...

  ngOnInit() {
    // initialization code block
  }
}

Mention that Angular(Version2+) provides life hook for a component from been created to been destroyed.


For ng-init at ng-repeat part, From Angular2, you should use ngFor instead and ngFor only allows a limited set of local variables to be defined, see DOC.

5 Comments

Unfortunately, it behaved differently from ng-init in which I can initialize the values within the scope of directive. What if the array comes from an API and you don't have any idea how many objects the API will respond. I'm trying to solve the problem without looping through the array just to initialize the toggle boolean.
@MichaelArdan you meant to ask about ng-init at ng-repeat block?
Sorry if the question confused you. Yeah, I'm talking about the ng-init in my ng-repeat block. Edited the question
@MichaelArdan ngFor only allows a limited set of local variables to be defined. see angular.io/api/common/NgForOf#local-variables
It seems that the same solution is not achievable in NG++. Thanks Pengyy
0

I did not understand your request, could you explain yourself better? why do not you try to use the @component ...

@Component({
  selector: 'tag-selector',
  templateUrl: './pagina.html',
  styleUrls: ['./pagina.css']
})
export class Controller{
  your code
}

Edit:

if you declare the $scope out of Init, it should work anyway

angular.module("app", [])

.controller("controller", function($scope) {

  $scope.init = function() {

  };
  $scope.modules = [{
    label: 'Module A',
    children: [
      'Module A - 1',
      'Module A - 2',
      'Module A - 3'
    ]
  }, {
    label: 'Module B',
    children: [
      'Module B - 1',
      'Module B - 2',
      'Module B - 3'
    ]
  }, {
    label: 'Module C',
    children: [
      'Module C - 1',
      'Module C - 2',
      'Module C - 3'
    ]
  }];

});

I'm sorry, but I'm not sure I fully understood the question ...

1 Comment

Hi Marco! The question was confusing sorry. I had to edit the question to clarify things. I was talking about ng-init beside my ng-repeat. In my sample, I have 3 toggle variables initialized. Changing the value of one of the toggle wouldn't affect the other 2 since it is declared only within the scope of the ng-repeat.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.