mardi 30 janvier 2018

Convert AngularJS indeterminate checkbox to Angular 5

I have an AngularJS (1.5) setup for making a parent checkbox indeterminate if one of its children is selected as well as selecting all the children if the parent is selected.

I'm having trouble converting the old ES5 JS to typescript.

Here's the old controller:

  var _this = this;

_this.hierarchicalData = [
  {
    id: 0,
    label: 'Parent item',
    checked: false,
    children: [
      { id: 0, label: 'Child one', value: 'child_one', checked: false },
      { id: 1, label: 'Child two', value: 'child_two', checked: false },
      { id: 2, label: 'Child three', value: 'child_three', checked: false }
    ]
  }
];

_this.selectedChildren = [];
_this.isIndeterminate = false;
_this.allRowsSelected = false;

_this.selectChildren = function (data, $event) {
  var parentChecked = data.checked;
  angular.forEach(_this.hierarchicalData, function (value, key) {
    angular.forEach(value.children, function (value, key) {
      value.checked = parentChecked;
    });
  });
};

_this.selectChild = function (data, $event) {
  if (_this.selectedChildren.indexOf(data.id) === -1) {
    _this.selectedChildren.push(data.id);
    data.selected = true;
  } else {
    _this.selectedChildren.splice(_this.selectedChildren.indexOf(data.id), 1);
    _this.allRowsSelected = false;
    data.selected = false;
  }
};

// for the purposes of this demo, check the second child checkbox
_this.selectedChildren.push(1);
_this.hierarchicalData[0].children[1].checked = true;

and the old template:

 <ul class="list-nomarkers">
  <li ng-repeat="parent in check.hierarchicalData">
    <div class="checkbox">
      <label>
        <input type="checkbox" ng-model="parent.checked" ng-click="check.selectChildren(parent, $event)" ui-indeterminate="check.selectedChildren.length">
      </label>
    </div>
    <ul class="list-nomarkers">
      <li ng-repeat="child in parent.children">
        <div class="checkbox">
          <label>
            <input type="checkbox" ng-model="child.checked" ng-click="check.selectChild(child, $event)"> 
          </label>
        </div>

      </li>
    </ul>
  </li>
</ul>

I updated the template for Angular 5:

   <ul class="list-unstyled">
     <li *ngFor="let parent of hierarchicalData">
      <div class="form-check">
        <input class="form-check-input" type="checkbox" [(ngModel)]="parent.checked" (click)="selectChildren(parent, $event)">
        <label class="form-check-label">
         
        </label>
      </div>
      <ul class="list-unstyled">
        <li *ngFor="let child of parent.children">
          <div class="form-check">
            <input class="form-check-input" type="checkbox" [(ngModel)]="child.checked" (click)="selectChild(parent, $event)">
            <label class="form-check-label">
              
            </label>
          </div>
        </li>
      </ul>
     </li>
   </ul>

And added the 2 main functions to the component:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'pb-ds-checkboxes',
  templateUrl: './checkboxes.component.html'
})
export class CheckboxesComponent implements OnInit {
  hierarchicalData = [
    {
      id: 0,
      label: 'Parent item',
      checked: false,
      children: [
        { id: 0, label: 'Child one', value: 'child_one', checked: false },
        { id: 1, label: 'Child two', value: 'child_two', checked: false },
        { id: 2, label: 'Child three', value: 'child_three', checked: false }
      ]
    }
  ];
  selectedChildren = [];
  isIndeterminate = false;
  allRowsSelected = false;
  constructor() {}

  ngOnInit() {}

  selectChildren = function(data, $event) {
    const parentChecked = data.checked;
    angular.forEach(this.hierarchicalData, function (value, key) {
      angular.forEach(value.children, function (value, key) {
        value.checked = parentChecked;
      });
    });
  };

  selectChild = function(data, $event) {
    if (this.selectedChildren.indexOf(data.id) === -1) {
      this.selectedChildren.push(data.id);
      data.selected = true;
    } else {
      this.selectedChildren.splice(this.selectedChildren.indexOf(data.id), 1);
      this.allRowsSelected = false;
      data.selected = false;
    }
  };
}

Obviously, I need to convert the old angular.forEach into ES6, but I'm still a little weak on arrow functions. Can someone please give me a nudge in the right direction?




Aucun commentaire:

Enregistrer un commentaire