What I want to achieve is to create a component consisting of a dropdown list of dynamically populated checkboxes. - DONE
These checkboxes should fetch the names for the values inside the directive from an attribute property-name
of a directive element. - DONE
They need to return the values (which of them are selected) to a variable in $scope
which name is the same as the attribute my-model
so I could read it from the main page referencing to $scope.firstTitle
and $scope.secondTitle
as in plunker. - This is my problem
The most important part is that the solution should allow to insert many components on the same page without the variable in $scope
of the previous component be overwritten by next one.
I've tried searching for an answer but none seem to address my exact issue which is populating values from one source to a template and passing the values from template to $scope
.
Here's a plunker of what I've already achieved: https://plnkr.co/edit/Uwarzh7qxrE3pDKxH2u8?p=preview
HTML:
<div ng-app="testModule" ng-controller="componentsController">
<div class="container col-md-3">
<mydropdown property-name="First Title" my-model="firstTitle"></mydropdown>
</div>
<div class="container col-md-3">
<mydropdown property-name="Second Title" my-model="secondTitle"></mydropdown>
</div>
<button class="btn btn-success" type="submit" value="Save" ng-click="testSave()">Test data output</button>
</div>
JS:
angular.module('testModule', [])
.controller('componentsController', ["$scope", function ($scope) {
$scope.testSave = function() {
console.log($scope);
}
}])
.directive('mydropdown', function () {
return {
scope: {
propertyName: '@',
myModel:'='
},
templateUrl: 'component.html',
link: function (scope) {
// this will be replaced with call to service
scope.dropDowns = [
{
value: 'test1',
text: 'Test1'
},
{
value: 'test2',
text: 'Test2'
}
];
}
}
});
Component.html:
<div class="dropdown">
<button class="btn btn-block btn-default dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="pull-left">{{propertyName}}</span>
<i class="pull-right glyphicon glyphicon-triangle-bottom"></i>
</button>
<ul class="dropdown-menu">
<li ng-repeat="dropDown in dropDowns">
<div class="checkbox col-md-12">
<label>
<input type="checkbox" ng-model="dropDown.value"> {{dropDown.text}}
</label>
</div>
</li>
</ul>
</div>
Please help.
Put the model in the main controller:
app.controller("mainCtrl", function() {
var vm = this;
vm.firstDropdowns = [
{
value: 'test1',
text: 'Test1'
},
{
value: 'test2',
text: 'Test2'
}
];
})
Connect with the component in the template:
<mydropdown my-model="vm.firstDropdowns">
</mydropdown>
Use one-way &
binding in the component:
app.component('mydropdown', {
bindings: {
myModel: '<',
},
template: `
<div ng-repeat="dropDown in $ctrl.myModel">
<input type="checkbox" ng-model="dropDown.value" />
{{dropDown.text}}
</div>
`
})
Because the input is an object, the ng-model
directives inside the component will update the contents of the object and changes will be seen by the parent controller.
angular.module("app",[])
.controller("mainCtrl", function() {
var vm = this;
vm.firstDropdowns = [
{
value: 'test1',
text: 'Test1'
},
{
value: 'test2',
text: 'Test2'
}
];
})
.component('mydropdown', {
bindings: {
myModel: '<',
},
template: `
<div ng-repeat="dropDown in $ctrl.myModel">
<input type="checkbox" ng-model="dropDown.value" />
{{dropDown.text}}
</div>
`
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="mainCtrl as vm">
<fieldset>
<mydropdown my-model="vm.firstDropdowns">
</mydropdown>
</fieldset>
<fieldset>
<div ng-repeat="x in vm.firstDropdowns">
{{x.value}} {{x.text}}
</div>
</fieldset>
</body>