[英]DOM Manipulation from Component in Angular 1.5+
I have created a custom directive for dropdown. 我已经为下拉列表创建了一个自定义指令。 I want to show/hide UI elements when the ng-change event is fired on that dropdown.
我想在该下拉列表上触发ng-change事件时显示/隐藏UI元素。
This is the plunkr link to my code. 这是我的代码的plunkr链接。
The 'onCarChange()' method is getting called but the UI elements are not being hidden or shown based on the selection. 调用'onCarChange()'方法,但不会根据选择隐藏或显示UI元素。
I am still learning AngularJS, so if I am taking a wrong approach then kindly let me know. 我还在学习AngularJS,所以如果我采取了错误的方法,那么请告诉我。
HTML markup 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 code 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;
}
}
select-car.html 选择-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
scope for components is always isolate. 组件的范围始终是隔离的。 you have two options.
你有两个选择。 option one is to use a directive instead.
选项一是使用指令代替。 ( plunkr )
( plunkr )
angular
.module('RedBlack.components', [])
.directive('selectCar', function() {
return {
restrict: 'E',
templateUrl: 'select-car.html',
transclude: true,
controller: CarsController,
controllerAs: 'vm'
};
});
If you want to use a component one option is to pass the value into it. 如果要使用组件,则一个选项是将值传递给它。 ( plunkr ) Notice it would be better to pass something like a model (eg car) into the component and use events for changing the dropdown, but you got the point.
( plunkr )请注意,最好将类似模型(例如汽车)的东西传递到组件中并使用事件来更改下拉列表,但是你明白了。
1) define controller on outer scope and pass it into component 1)在外部范围上定义控制器并将其传递给组件
<html ng-app="RedBlack" ng-controller="CarsController as vm">
...
<select-car parent="vm"></select-car>
...
</html>
2) bind value to isolate scope of component 2)绑定值以隔离组件的范围
angular
.module('RedBlack.components', [])
.component('selectCar', {
restrict: 'E',
templateUrl: 'select-car.html',
bindings: { parent: "=" }, // = means two way data binding
controllerAs: "vm"
});
3) adjust template 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>
Here is my refactor for your code 这是我的代码重构
index.html 的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 //as main 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;
}
}
component 零件
select-car.html 选择-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 // must become as select-car.component.js 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'
});
The component you've created should be seen as an isolated component. 您创建的组件应被视为一个独立的组件。 Therefor the
vm.showDataGrid
and vm.disableRunButton
are not accessible outside the component template. 因此,组件模板外部无法访问
vm.showDataGrid
和vm.disableRunButton
。
If this is desired, you can do two things: 如果需要,您可以做两件事:
I tend to favor the second approach. 我倾向于采用第二种方法。 See this plunkr for an implementation: https://plnkr.co/edit/RG51ADtvHuRSJDUMv6mV?p=preview
请参阅此plunkr了解实现: https ://plnkr.co/edit/RG51ADtvHuRSJDUMv6mV?p = preview
The core is in the new implementation of the CarsController: 核心是在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();
}
Then you can simply use ng-model on your new component from html: 然后你可以简单地在html的新组件上使用ng-model:
<select-car ng-model="selectedCar"></select-car>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.