disable button if none of the options are selected angularJS - javascript

I would like to disable the add button if none of the options in the list are selected or if the selected class is not there in the list.
HTML:
<div ng-repeat="json in myJson" ng-class="{'selected': json.selected}" ng-model="selectionOptions" ng-click="selectItem($index)">
{{json.title}}
</div>
<button ng-disabled="hideAdd">Add</button>
I have tried:
$scope.$watch('selectionOptions', function(val) {
if(angular.element('selectionOptions').hasClass('selected')) {
$scope.hideAdd = false;
} else {
$scope.hideAdd = true;
}
});
JSFiddle Demo

No need for a directive or a $watch.
Remove the ng-model as it's doing nothing. Even if it did work every item would be bound to the same variable.
Use ng-click to call a function on $scope which toggles the selected value and adds/removes it from the list of selected options.
You can use ng-show="selectedOptions.length" to hide/show the add button.
angular.module('app', []).controller('mainCtrl', function($scope) {
$scope.myJson = [{
title: 'test1',
selected: false
}, {
title: 'test2',
selected: true
}, {
title: 'test3',
selected: false
}, {
title: 'test4',
selected: false
}];
// Initialize array with already selected options
$scope.selectedOptions = $scope.myJson.filter(function(item) {
return item.selected;
});
$scope.toggle = function(item) {
// Toggle selected
item.selected = !item.selected;
// Add it to list
if (item.selected) {
$scope.selectedOptions.push(item);
} else {
// Remove it from list
$scope.selectedOptions.splice($scope.selectedOptions.indexOf(item), 1);
}
};
});
.selected {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='mainCtrl'>
<div app-click="">
<div ng-repeat="json in myJson" ng-click="toggle(json)" ng-class="{'selected': json.selected}">
{{json.title}}
</div>
<button ng-show="selectedOptions.length">Add</button>
</div>
<br/>Selected options: <pre>{{selectedOptions | json}}</pre>
</div>

I don't think you can use ng-model here, since there is no input.
You can watch the json or you can use a filter to determine if there are any selected elements. Example of the latter:
.directive('appClick', function() {
return {
restrict: 'A',
scope: true,
controller: function($scope, $element) {
optionIsSelected();
function optionIsSelected() {
$scope.hideAdd = $scope.myJson.filter(function(el) {
return el.selected
}).length === 0;
}
$scope.selectItem = function(index) {
$scope.myJson[index].selected = !($scope.myJson[index].selected);
optionIsSelected();
};
}
}
}
Working fiddle

Related

Angular ng-change not working for checkboxes

Here is my code below. The ng-change of individual checkboxes is not getting triggered when it is changed by clicking Select All button but it is getting triggered when it's selected individually. I need the itemChecked method to be triggered when the Select All button is clicked.
Here is a Codepen Link for the same
HTML
<div ng-app="Test">
<div ng-controller="TestController">
<form>
<div ng-repeat="item in list track by $index">
<input type="checkbox" ng-model="item" ng-change="itemChecked($index)">{{$index + 1}}
</div>
</form>
<button ng-click="toggleSelection()">Select all</button>
</div>
</div>
JavaScript
var app = angular.module("Test", []);
app.controller("TestController", [
"$scope",
"$http",
function($scope, $http) {
$scope.list = [false, false, false, false, false];
$scope.itemChecked = function(i) {
console.log(i);
};
$scope.toggleSelection = function() {
for (var i in $scope.list) {
$scope.list[i] = true;
}
};
}
]);
Please let me know what I need to change or what I am doing wrong to fix this.
You have set wrong variable in ng-model. The ng-model section should be:
ng-model="list[$index]"
To listen the collection, you have to use the following:
$scope.$watchCollection
It is working perfectly in the following code, check the code snippet:
var app = angular.module("Test", []);
app.controller("TestController", [
"$scope",
"$http",
function($scope, $http) {
$scope.list = [false, false, false, false, false];
$scope.itemChecked = function(i) {
console.log(i);
console.log($scope.list[i]);
};
$scope.$watchCollection('list', function (oldValue, newValue) {
//console.log(oldValue);
//console.log(newValue);
//console.log($scope.list);
for(var i = 0; i < oldValue.length;i++){
if (oldValue[i]!==newValue[i]) {
$scope.itemChecked(i);
}
}
});
$scope.toggleSelection = function() {
for (var i in $scope.list) {
$scope.list[i] = true;
}
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="Test">
<div ng-controller="TestController">
<form>
<div ng-repeat="item in list track by $index">
<input type="checkbox" ng-model="list[$index]" ng-change="itemChecked($index)">{{$index + 1}}
</div>
</form>
<button ng-click="toggleSelection()">Select all</button>
</div>
</div>
What you need is watchCollection method. ngChange works only if the value is changed from HTML. It is not triggered when the value is changed from controller.
app.controller("TestController", [
"$scope",
"$http",
function($scope, $http) {
$scope.list = [false, false, false, false, false];
$scope.itemChecked = function(i) {
console.log(i);
};
$scope.toggleSelection = function() {
for (var i in $scope.list) {
$scope.list[i] = true;
}
};
/*********************************************************/
$scope.$watchCollection('list', function (newVal, oldVal) {
console.log('collection changed') });
}
/*********************************************************/
]);
Or If you just want itemChecked method to be called whenever the selectAll button is clicked, Then just call itemChecked inside toggleSelection method.
$scope.toggleSelection = function() {
for (var i in $scope.list) {
$scope.list[i] = true;
$scope.itemChecked(i);
}
};

AngularJS Directive with Select

I have a problem using angular 1.6.5 and tried everything but without any noticeable progress...
I made a directive that implement the HTML SELECT tag, the component seems to work until I try to get the entire object in option value attribute instead of a single value or ID.
I can output the text of the option tag both as a property of the object or trough a function the return some string.
Here is a complete fiddle with the component and the problem.
There are 3 examples:
The 1st one seems to work correctly, it print the correct text and return the correct value
The 2nd: do not work, I'd like to set to the model the entire OBJECT selected and not a property
The 3rd: do not work, I'd like to set to the model the entire OBJECT selected and not a property but it print correctly the text from a function in parent controller.
How can I change my component that it can return both a property (like ID) both the entire object (JSON format is good)?
angular.module("myApp", ['customDrop']).controller("TestController", ['$scope', function($scope) {
var ITEM_SELECTED = {
ID: 3,
VALUE: "VALUE3"
};
$scope.LIST = [{
ID: 1,
VALUE: "VALUE1"
},
{
ID: 2,
VALUE: "VALUE2"
},
ITEM_SELECTED,
];
$scope.OBJ = {
LOTTO1: ITEM_SELECTED,
LOTTO2: ITEM_SELECTED,
LOTTO3: ITEM_SELECTED
};
$scope.getCompleteValue = function(obj) {
return obj.ID + " - " + obj.VALUE;
}
}]);
angular.module('customDrop', []).directive('customDrop', function() {
return {
restrict: 'E',
scope: {
dropid: '#',
dropvalue: '&',
list: '=',
ngModel: '='
},
require: 'ngModel',
template: '<select class="drop" ng-model="ngModel">' +
'<option ng-repeat="val in list" value="{{getId(val)}}">{{getValue(val)}}</option>' +
'</select>',
controller: ['$scope', '$parse', '$timeout',
function($scope, $parse, $timeout) {
$scope.getId = function(obj) {
return obj[$scope.dropid];
}
// Can print text option as proerty of through function in parent scope.
$scope.getValue = function(obj) {
return !angular.isFunction($scope.dropvalue(obj)) ?
$scope.dropvalue(obj) :
$parse($scope.dropvalue(obj))(obj);
}
}
]
}
});
.drop {
width: 400px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<div ng-app="myApp" ng-controller="TestController">
<strong>Simple Text Property (drop id intended to return the ID): (working)</strong><br>
<custom-drop dropvalue="VALUE" dropid="ID" list="LIST" ng-model="OBJ.LOTTO1"></custom-drop><br> Selected Value: {{OBJ.LOTTO1}}
<br><br><br>
<!-- using property as dropValue -->
<strong>Simple Text Property (drop id intended to return an object): (not working)</strong><br>
<custom-drop dropvalue="VALUE" dropid="" list="LIST" ng-model="OBJ.LOTTO2"></custom-drop><br> Selected Value: {{OBJ.LOTTO2}}
<br><br><br>
<!-- using function as dropValue -->
<strong>Function Text Property: (not working)</strong><br>
<custom-drop dropvalue="getCompleteValue" dropid="" list="LIST" ng-model="OBJ.LOTTO3"></custom-drop><br> Selected Value: {{OBJ.LOTTO3}}
</div>
To set to the model the entire OBJECT selected you have to modify your getId() method to return the object in case $scope.dropid was not passed through the bindings (since this method is used to generate the value of the option). Also I recommend using ngOptions to generate the list of option elements. See the snippet below:
angular.module("myApp", ['customDrop']).controller("TestController", ['$scope', function ($scope) {
var ITEM_SELECTED = {
ID: 3,
VALUE: "VALUE3"
};
$scope.LIST = [{
ID: 1,
VALUE: "VALUE1"
},
{
ID: 2,
VALUE: "VALUE2"
},
ITEM_SELECTED,
];
$scope.OBJ = {
LOTTO1: ITEM_SELECTED.ID,
LOTTO2: ITEM_SELECTED,
LOTTO3: ITEM_SELECTED
};
$scope.getCompleteValue = function (obj) {
return obj.ID + " - " + obj.VALUE;
}
}]);
angular.module('customDrop', []).directive('customDrop', function () {
return {
restrict: 'E',
scope: {
dropid: '#',
dropvalue: '&',
list: '<',
ngModel: '='
},
require: 'ngModel',
template: '<select class="drop" ng-model="ngModel" ng-options="getModelValue(val) as getOptionText(val) for val in list"></select>',
controller: ['$scope', '$parse',
function ($scope, $parse) {
$scope.getModelValue = function (obj) {
return !!$scope.dropid ? obj[$scope.dropid] : obj;
};
$scope.getOptionText = function (obj) {
return !angular.isFunction($scope.dropvalue(obj)) ?
$scope.dropvalue(obj) :
$parse($scope.dropvalue(obj))(obj);
}
}
]
}
});
.drop {
width: 400px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<div ng-app="myApp" ng-controller="TestController">
<strong>Simple Text Property (drop id intended to return the ID): </strong><br>
<custom-drop dropvalue="VALUE" dropid="ID" list="LIST" ng-model="OBJ.LOTTO1"></custom-drop><br> Selected Value: {{OBJ.LOTTO1}}
<br><br><br>
<!-- using property as dropValue -->
<strong>Simple Text Property (drop id intended to return an object): </strong><br>
<custom-drop dropvalue="VALUE" dropid="" list="LIST" ng-model="OBJ.LOTTO2"></custom-drop><br> Selected Value: {{OBJ.LOTTO2}}
<br><br><br>
<!-- using function as dropValue -->
<strong>Function Text Property: </strong><br>
<custom-drop dropvalue="getCompleteValue" dropid="" list="LIST" ng-model="OBJ.LOTTO3"></custom-drop><br> Selected Value: {{OBJ.LOTTO3}}
</div>

AngularJS toggle button filters

So this is a javascript conversion from jQuery app into Angular app. The current jQuery app works but is needed to make into a real app using the Angular framework.
The logic behind the whole app is to select categories and filter OUT and get specific results based on the filter buttons. So lets say you want only to see results that include only where filter 1 AND filter 2 are together, but not (filter1, filter2, and filter1+filter2). see the jquery version: demo
$(document).ready(function(){
$('.filter-selector').click(function(){
/* Filter 1 Categories */
if($(this).attr("value")==".filter1_group1"){
$(".filter1_group1-show").toggle();
$(this).toggleClass('active');
}
if($(this).attr("value")==".filter1_group2"){
$(".filter1_group2-show").toggle();
$(this).toggleClass('active');
}
});
});
Now I need to convert that javascript magic over to angular, keep the buttons in a toggle stat and show results on the second view. It will essentially be an Angular SPA with 2 views: 1 for filters and 1 for results. Previous app was using jQuery toggle class function, but there is no built in function for Angular in this case. All the examples for toggle button for Angular have only 1 toggle button that hides/shows divs. And other example buttons only show or hide divs separately and are not toggle buttons. And how do I turn filter results into service return and then inject that into View 2 as results and show them?
Need some direction from Angular gods here...
UPDATE 1: thanx to Shaun Scovil, the Angular way of creating this filter groups was found. However the filter group works well on a single page but not in 2 view SPA app: plunkr The filters will break after switching between filters and cases a few times.
UPDATE 2: thanx to Shaun Scovil once more, the filters/cases toggle buttons work now going from page view to page view back to any number of views: plunkr
Based on your example app and description, here is how I would describe what you need in Angular terms:
a controller for your filter toggles view
a controller for your cases view
a service to store toggled filters
a directive for your filter toggle buttons
a filter to reduce the list of cases by toggled filters
Working example: JSFiddle (UPDATED to work with ngRoute)
Controllers
The two controllers should serve as view models, providing some well-formed data that can be used in their respective view templates. For example:
angular.module('myApp')
.controller('FilterToggleController', FilterToggleController)
.controller('CasesController', CasesController)
;
function FilterToggleController() {
var vm = this;
vm.filterGroups = {
1: [1,2],
2: [1,2]
};
}
function CasesController() {
var vm = this;
vm.cases = [
{label:'Case 1,2', filters:[{group:1, filter:1}, {group:1, filter: 2}]},
{label:'Case 1', filters:[{group:1, filter:1}]},
{label:'Case 2', filters:[{group:1, filter:2}]},
{label:'Case 1,3', filters:[{group:1, filter:1}, {group:2, filter:1}]},
{label:'Case 4', filters:[{group:2, filter:2}]}
];
}
Service
The purpose of an Angular service is to share data or functionality among controllers, directives, filters and other services. Your service is a data store for the selected filters, so I would use a $cacheFactory cache under the hood. For example:
angular.module('myApp')
.factory('$filterCache', filterCacheFactory)
;
function filterCacheFactory($cacheFactory) {
var cache = $cacheFactory('filterCache');
var $filterCache = {};
$filterCache.has = function(group, filter) {
return cache.get(concat(group, filter)) === true;
};
$filterCache.put = function(group, filter) {
cache.put(concat(group, filter), true);
}
$filterCache.remove = function(group, filter) {
cache.remove(concat(group, filter));
}
$filterCache.count = function() {
return cache.info().size;
}
function concat(group, filter) {
return group + ':' + filter;
}
return $filterCache;
}
Directive
A directive adds functionality to an HTML element. In your case, I would create a directive with a 'click' event handler that can be added as an attribute to a button or any other element. Our $filterCache service could be used by the event handler to keep track of the group/filter combination that the button represents. For example:
angular.module('myApp')
.directive('toggleFilter', toggleFilterDirective)
;
function toggleFilterDirective($filterCache) {
return function(scope, iElement, iAttrs) {
var toggled = false;
iElement.on('click', function() {
var group = scope.$eval(iAttrs.group);
var filter = scope.$eval(iAttrs.filter);
toggled = !toggled;
if (toggled) {
$filterCache.put(group, filter);
iElement.addClass('toggled');
} else {
$filterCache.remove(group, filter);
iElement.removeClass('toggled');
}
scope.$apply();
});
};
}
Filter
The purpose of the filter is to take the array of case objects defined in CasesController and reduce them based on the filters stored in our $filterCache service. It will reduce the list to an empty array if no filters are toggled. For example:
angular.module('myApp')
.filter('filterCases', filterCasesFactory)
;
function filterCasesFactory($filterCache) {
return function(items) {
var filteredItems = [];
var filterCount = $filterCache.count();
if (filterCount) {
angular.forEach(items, function(item) {
if (angular.isArray(item.filters) && item.filters.length >= filterCount) {
for (var matches = 0, i = 0; i < item.filters.length; i++) {
var group = item.filters[i].group;
var filter = item.filters[i].filter;
if ($filterCache.has(group, filter))
matches++;
if (matches === filterCount) {
filteredItems.push(item);
break;
}
}
}
});
}
return filteredItems;
};
}
Template
Finally, the HTML template ties it all together. Here is an example of how that would look using all of the other pieces we've built:
<!-- Filter Toggles View -->
<div ng-controller="FilterToggleController as vm">
<div ng-repeat="(group, filters) in vm.filterGroups">
<h2>
Group {{group}}
</h2>
<div ng-repeat="filter in filters">
<button toggle-filter group="group" filter="filter">
Filter {{filter}}
</button>
</div>
</div>
</div>
<!-- Cases View -->
<div ng-controller="CasesController as vm">
<h2>
Your Cases
</h2>
<ol>
<li ng-repeat="case in vm.cases | filterCases">
{{case.label}}
</li>
</ol>
</div>
UPDATE
Based on the comments, I updated the JSFiddle example to work with ngRoute by making the following changes to the toggleFilterDirective:
function toggleFilterDirective($filterCache) {
return function(scope, iElement, iAttrs) {
var group, filter, toggled;
sync();
update();
iElement.on('click', onClick);
scope.$on('$destroy', offClick);
function onClick() {
sync();
toggle();
update();
scope.$apply();
}
function offClick() {
iElement.off('click', onClick);
}
function sync() {
group = scope.$eval(iAttrs.group);
filter = scope.$eval(iAttrs.filter);
toggled = $filterCache.has(group, filter);
}
function toggle() {
toggled = !toggled;
if (toggled) {
$filterCache.put(group, filter);
} else {
$filterCache.remove(group, filter);
}
}
function update() {
if (toggled) {
iElement.addClass('toggled');
} else {
iElement.removeClass('toggled');
}
}
};
}
Here is a link to the original example: JSFiddle
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<script>
var app = angular.module('App', []);
app.service('serviceFilters', function() {
var filters = [
{
name: 'Filter 1',
groups: [
{
name: 'Group 1',
selected: false
},
{
name: 'Group 2',
selected: false
}
]
},
{
name: 'Filter 2',
groups: [
{
name: 'Group 1',
selected: false
},
{
name: 'Group 2',
selected: false
}
]
}
],
getFilters = function () {
return filters;
},
isCase12Selected = function () {
return filters[0].groups[0].selected && filters[0].groups[1].selected && !filters[1].groups[0].selected && !filters[1].groups[1].selected;
},
isCase1Selected = function () {
return filters[0].groups[0].selected && !filters[0].groups[1].selected && !filters[1].groups[0].selected && !filters[1].groups[1].selected;
},
isCase2Selected = function () {
return !filters[0].groups[0].selected && filters[0].groups[1].selected && !filters[1].groups[0].selected && !filters[1].groups[1].selected;
},
isCase13Selected = function () {
return filters[0].groups[0].selected && !filters[0].groups[1].selected && filters[1].groups[0].selected && filters[1].groups[1].selected;
},
isCase4Selected = function () {
return !filters[0].groups[0].selected && !filters[0].groups[1].selected && !filters[1].groups[0].selected && filters[1].groups[1].selected;
};
return {
getFilters: getFilters,
isCase12Selected: isCase12Selected,
isCase1Selected: isCase1Selected,
isCase2Selected: isCase2Selected,
isCase13Selected: isCase13Selected,
isCase4Selected: isCase4Selected
};
});
app.filter('selectedGroups', function() {
return function(groups) {
return groups.filter(function (group) {
return group.selected;
});
};
});
app.directive(
'viewApplication',
[
'serviceFilters',
function (serviceFilters) {
'use strict';
return {
restrict: 'E',
template:
'<div>' +
'<view-filters></view-filters>' +
'<view-selected></view-selected>' +
'<view-cases></view-selected>' +
'</div>',
controller: ['$scope', function ($scope) {
$scope.serviceFilters = serviceFilters;
}]
};
}
]
);
app.directive(
'viewFilters',
[
'serviceFilters',
function (serviceFilters) {
'use strict';
return {
restrict: 'E',
scope: {},
template:
'<div>' +
'<h1>Filters</h1>' +
'<div ng-repeat="filter in serviceFilters.getFilters()">' +
'<h2>{{::filter.name}}</h2>' +
'<div ng-repeat="group in filter.groups">' +
'<span>{{::group.name}} </span>' +
'<button ng-click="group.selected=!group.selected">{{group.selected ? \'Unselect\' : \'Select\'}}</button>' +
'</div>' +
'</div>' +
'</div>',
controller: ['$scope', function ($scope) {
$scope.serviceFilters = serviceFilters;
}]
};
}
]
);
app.directive(
'viewSelected',
[
'serviceFilters',
function (serviceFilters) {
'use strict';
return {
restrict: 'E',
scope: {},
template:
'<div>' +
'<h1>Selected</h1>' +
'<div ng-repeat="filter in serviceFilters.getFilters()">' +
'<div ng-repeat="group in filter.groups | selectedGroups">' +
'{{filter.name}} | {{group.name}}' +
'</div>' +
'</div>' +
'</div>',
controller: ['$scope', function ($scope) {
$scope.serviceFilters = serviceFilters;
}]
};
}
]
);
app.directive(
'viewCases',
[
'serviceFilters',
function (serviceFilters) {
'use strict';
return {
restrict: 'E',
scope: {
filters: '='
},
template:
'<div>' +
'<h1>Cases</h1>' +
'<span ng-if="serviceFilters.isCase12Selected()">Case 1,2</span>' +
'<span ng-if="serviceFilters.isCase1Selected()">Case 1</span>' +
'<span ng-if="serviceFilters.isCase2Selected()">Case 2</span>' +
'<span ng-if="serviceFilters.isCase13Selected()">Case 1,3</span>' +
'<span ng-if="serviceFilters.isCase14Selected()">Case 4</span>' +
'</div>',
controller: ['$scope', function ($scope) {
$scope.serviceFilters = serviceFilters;
}]
};
}
]
);
</script>
</head>
<body ng-app="App">
<view-application></view-application>
</body>
</html>

angularjs x editable controls lose focus after done or cancel

I have basic x-editable controls such as input fields or select. I just wish to retain focus after I am done with the control.
template:
<div ng-controller="Ctrl">
{{ user.name || 'empty' }}
</div>
controller:
app.controller('Ctrl', function($scope, $filter) {
$scope.user = {id: 1, name: 'name1'};
});
Please see a live version of the problem:
http://plnkr.co/edit/BjWwXIlYyyLvRnVwO8m8?p=preview
I added a blur function but i cant seem to modify it correctly to do so. If there are other solutions, i would like to know.
#heyNow, the outline of the solution is this:
Create a non-isolate 'focus' directive and apply it to the link element. This should take a boolean, where true sets the focus
Create an onhide function that makes the condition in the 'focus' directive true
create an 'unsetFocus' function which sets the 'focus' condition to false and should be called with ng-blur and onshow.
here is the html
<a href="#" onhide="onhide(user)" onshow="unsetFocus()"
ng-blur="unsetFocus()" focus="focusObj==user"
editable-text="user.name">
{{ user.name || 'empty' }}
</a>
and the directive and controller:
app.directive('focus', function($timeout) {
return {
scope: false,
link: function(scope, element, attrs) {
scope.$watch(attrs.focus, function(newval,oldval) {
if (newval) {
$timeout(function() {
element[0].focus();
});
}
});
}
};
});
app.controller('Ctrl', function($scope, $filter) {
$scope.user = {
name: 'awesome user',
status: 2
};
$scope.onhide = function(obj) {
$scope.focusObj = obj;
}
$scope.unsetFocus = function() {
$scope.focusObj = null;
}
}
check out this plunk

Angularjs: How to update parent scope in directive without using isolated scope when the attribute is passed in within ngRepeat

I have a simple angularjs directive that uses JQuery to convert a template to a draggable dialog
var myApp = angular.module("myApp", []);
myApp.controller('myCtrl', function ($scope) {
$scope.tasks = [{
name: 'learn angular',
show: false
}, {
name: 'build an angular app',
show: false
}];
$scope.showBox = function (taskname) {
for (var i = 0; i < $scope.tasks.length; i++) {
if ($scope.tasks[i].name === taskname) {
$scope.tasks[i].show = !$scope.tasks[i].show;
}
}
}
});
myApp.directive("draggableDialog", function () {
return {
template: 'task: {{task.name}}',
link: function (scope, element, attrs) {
element.dialog({
title : "My Dialog",
autoOpen: false
});
element.bind("dialogclose", function () {
if (!scope.$$phase) {
scope.$apply(function () {
scope[attrs.draggableDialog] = false; //here is the problem
});
}
});
scope.$watch(attrs.draggableDialog, function (v) {
if (v) {
element.dialog("open");
} else {
element.dialog("close");
}
});
}
}
});
I am using this directive in a ngRepeat
<div>
<h2>Draggable Dialog</h2>
<div ng-controller="myCtrl">
<ul class="unstyled">
<li ng-repeat="task in tasks">
<button ng-click="showBox(task.name)">show {{task.name}}</button>{{task.show}}
<div draggable-dialog="task.show">test</div>
</li>
</ul>
</div>
</div>
Refer to this fiddle: http://jsfiddle.net/tianhai/BEtPk/#base
When the user manually close the dialog, I can detect the event and I want to set $scope.task[i].show in myCtrl to false. How can I do it? I am not able to use isolated scope two way binding as I am using this directive together with another directive also taking in $scope.task.
You have attrs.draggableDialog set to "task.show" so when you do
scope[attrs.draggableDialog] = false you end up with a element attached to scope that you could access with scope['task.show'] which is different than scope['task']['show'] or scope.task.show
To generically set a parent variable to false you need to eval a string containing the assignment. For you it would look like this:
scope.$eval(attrs.draggableDialog + ' = false;');
Hope this helped

Categories

Resources