簡體   English   中英

Angular 1.5+中Component的DOM操作

[英]DOM Manipulation from Component in Angular 1.5+

我已經為下拉列表創建了一個自定義指令。 我想在該下拉列表上觸發ng-change事件時顯示/隱藏UI元素。

這是我的代碼的plunkr鏈接。

調用'onCarChange()'方法,但不會根據選擇隱藏或顯示UI元素。

我還在學習AngularJS,所以如果我采取了錯誤的方法,那么請告訴我。

HTML標記

<div ng-app="RedBlack">
    <select-car></select-car> <-- element directive
    <p ng-show="vm.showDataGrid">DATA GRID</p>
    <button ng-show="!vm.disableRunButton">Run Button</button>
</div>

AngularJS代碼

angular
    .module('RedBlack', [])
    .component('selectCar', {
      restrict: 'E',
      templateUrl: 'select-car.html',
      bindings: {

      },
      transclude: true,
      controller: CarsController,
      controllerAs: 'vm',
      replace: true
    })
    .controller("CarsController", CarsController);

function CarsController() {
  var vm = this;      
  vm.showDataGrid = true;
  vm.disableRunButton = true;
  vm.myCars = {
    options: [
      { id: '1', name: 'LaFerrari' },
      { id: '2', name: 'Porsche 918' },
      { id: '3', name: 'McLaren P1' }
    ],
    selectedCar: { id: '2', name: 'Porsche 918' }
  };      
  vm.onCarChange = onCarChange;

  function onCarChange() {
    console.log("Called onCarChange()");
    vm.showDataGrid = false;
    vm.disableRunButton = false;
    return true;
  }

}

選擇-car.html

<div>
  <select class="form-control" ng-options="option.name for option in vm.myCars.options track by option.id"
  ng-model="vm.myCars.selectedCar"
  ng-change="vm.onCarChange()">
  </select>
</div

組件的范圍始終是隔離的。 你有兩個選擇。 選項一是使用指令代替。 plunkr

angular
  .module('RedBlack.components', [])
  .directive('selectCar', function() {
    return {
      restrict: 'E',
      templateUrl: 'select-car.html',
      transclude: true,
      controller: CarsController,
      controllerAs: 'vm'
    };
  });

如果要使用組件,則一個選項是將值傳遞給它。 plunkr )請注意,最好將類似模型(例如汽車)的東西傳遞到組件中並使用事件來更改下拉列表,但是你明白了。

1)在外部范圍上定義控制器並將其傳遞給組件

<html ng-app="RedBlack" ng-controller="CarsController as vm">
    ...
    <select-car parent="vm"></select-car>
    ...
</html>

2)綁定值以隔離組件的范圍

angular
  .module('RedBlack.components', [])
  .component('selectCar', {
    restrict: 'E',
    templateUrl: 'select-car.html',
    bindings: { parent: "=" }, // = means two way data binding
    controllerAs: "vm"
  });

3)調整模板

<div>
  <select class="form-control" ng-options="option.name for option in vm.parent.myCars.options track by option.id"
  ng-model="vm.parent.myCars.selectedCar"
  ng-change="vm.parent.onCarChange()">
  </select>
</div>

這是我的代碼重構

PLUNKER代碼

的index.html

<!DOCTYPE html>
<html ng-app="RedBlack">

  <head>
    <link rel="stylesheet" href="style.css">
    <script src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
    <script src="car.module.js"></script>
    <script src="selectCar.directive.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <div id="app" ng-controller='MainController as vm'>
    <h1>Hello a car!</h1>
    <select-car 
      on-car-changed='vm.carChange(car)'>
    </select-car>

    <p ng-show="!vm.showDataGrid">DATA GRID</p>

    <p>{{ vm.selected.name }}</p>

    <button ng-show="!vm.disableRunButton">Run Button</button>
    </div>
  </body>

</html>

car.module.js //作為主要

angular
  .module('RedBlack.cars', [])
  .controller("MainController", MainController);

function MainController() {

  var vm = this;

  vm.showDataGrid = true;
  vm.disableRunButton = true;

  vm.carChange = carChange;

  function carChange(car) {

    console.log("Called onCarChange()");
    console.log(car)

    vm.selected = car.name
    vm.showDataGrid = false;
    vm.disableRunButton = false;
  }

}

零件

選擇-car.html

<div>
  <select 
    class="form-control" 
    ng-options="item as item.name for item in vm.myCars track by item.id"
    ng-model="vm.selected"
    ng-change="vm.onCarChanged({car: vm.selected})">
  </select>
</div>

selectCar.directive.js //必須變為select-car.component.js

  angular
    .module('RedBlack.components', [])
    .component('selectCar', {
      templateUrl: 'select-car.html',
      bindings: {
        onCarChanged: '&'
      },
      controller: [function() {
        var vm = this;

          vm.myCars = [
              { id: 1, name: 'LaFerrari' },
              { id: 2, name: 'Porsche 918' },
              { id: 3, name: 'McLaren P1' }
          ];

          vm.selected = vm.myCars[0]
      }],
      controllerAs: 'vm'
    });

您創建的組件應被視為一個獨立的組件。 因此,組件模板外部無法訪問vm.showDataGridvm.disableRunButton

如果需要,您可以做兩件事:

  1. 選擇是一個事件
  2. 使組件使用ngModel,以便可以將其視為發出值的表單控件。

我傾向於采用第二種方法。 請參閱此plunkr了解實現: https ://plnkr.co/edit/RG51ADtvHuRSJDUMv6mV?p = preview

核心是在CarsController的新實現中:

function CarsController() {

}

CarsController.prototype.onCarChange = function() {
  // Because of the ng-model on the <select>, this.myCars.selectedCar is already
  // up to date.
  this.ngModel.$setViewValue(this.myCars.selectedCar);
}


CarsController.prototype.$onInit = function() {
  var vm = this;

  vm.ngModel.$render = function() {
   // This is called when the bound model value changes from external sources
    // vm.ngModel.$modelValue contains the new value, it may be a completely different
    // object, so set the selected to the one in the options
    vm.myCars.selectedCar = vm.myCars.options.find(function(item) {
      return vm.ngModel.$modelValue && item.id == vm.ngModel.$modelValue.id;
    });
  }



  vm.showDataGrid = true;
  vm.disableRunButton = true;

  vm.myCars = {
    options: [
      { id: '1', name: 'LaFerrari' },
      { id: '2', name: 'Porsche 918' },
      { id: '3', name: 'McLaren P1' }
    ],
    selectedCar: { id: '2', name: 'Porsche 918' }
  };
  // Initialize the ngModel value
  this.onCarChange();
}

然后你可以簡單地在html的新組件上使用ng-model:

<select-car ng-model="selectedCar"></select-car>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM