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>
Related
I want to dynamically compile component for inserting this to specific DOM element (DOM also dynamically created by 3rd party library).
So, I use $compile, $scope.
https://jsbin.com/gutekat/edit?html,js,console,output
// ListController $postLink life cycle hook
function $postLink() {
...
$timeout(function () {
ctrl.items.splice(0, 1);
$log.debug('First item of array is removed');
$log.debug(ctrl.items);
}, 2000);
}
but below $onChanges life cycle hook in ListItemController isn't executed.
// ListItemController $onChanges life cycle hook
function $onChanges(changes) {
if (!changes.item.isFirstChange()) {
$log.debug(changes); // Not executed
}
}
I guess that angular.merge to pass item before ListItemController controller instance initialization is a major cause.
var itemScope = $scope.$new(true, $scope);
itemScope = angular.merge(itemScope, {
$ctrl: {
item: item
}
});
I modified you code a bit to demonstrate what is going on w/ the one way binding.
angular.module('app', [
'list.component',
'list-item.component'
]);
/**
* list.component
*/
angular
.module('list.component', [])
.component('list', {
controller: ListController,
template: '<div id="list"></div>'
});
ListController.$inject = ['$compile', '$document', '$log', '$scope', '$timeout'];
function ListController($compile, $document, $log, $scope, $timeout) {
var ctrl = this;
ctrl.$onInit = $onInit;
ctrl.$postLink = $postLink;
function $onInit() {
ctrl.items = [
{
id: 0,
value: 'a'
},
{
id: 1,
value: 'b'
},
{
id: 2,
value: 'c'
}
];
}
function $postLink() {
var index = 0;
// Not entirely sure what you need to do this. This can easily be done in the template.
/** ie:
* template: '<div id="list" ng-repeat="item in $ctrl.items"><list-item item="item"></list-item></div>'
**/
var iElements = ctrl.items.map(function (item) {
var template = '<list-item item="$ctrl.items[' + (index) + ']"></list-item>';
index++;
// you don't want to create an isolate scope here for the 1 way binding of the item.
return $compile(template)($scope.$new(false));
});
var listDOM = $document[0].getElementById('list');
var jqListDOM = angular.element(listDOM);
iElements.forEach(function (iElement) {
jqListDOM.append(iElement);
});
$timeout(function () {
// this will trigger $onChanges since this is a reference change
ctrl.items[0] = { id: 3, value: 'ss' };
// this however, will not trigger the $onChanges, if you need to use deep comparison, consider to use $watch
ctrl.items[1].value = 's';
ctrl.items[2].value = 's';
}, 2000);
}
}
/**
* list-item.component
*/
angular
.module('list-item.component', [])
.component('listItem', {
bindings: {
item: '<'
},
controller: ListItemController,
template: '<div class="listItem">{{ $ctrl.item.value }}</div>'
});
ListItemController.$inject = ['$log'];
function ListItemController($log) {
var ctrl = this;
ctrl.$onChanges = $onChanges;
function $onChanges(changes) {
if (!changes.item.isFirstChange()) {
$log.debug(changes); // Not executed
}
}
}
I am working on a directive to create a custom dropdown. I have managed to bring the directive code to get it replaced.
Below is the directive tag in the html
<dropdown placeholder="Country.." list="count" selected="item" property="name"></dropdown>
Below is the html template that replaces the directive tag
<div class="dropdown-container" ng-class="{ show: listVisible }">
<div class="dropdown-list">
<div>
<div ng-repeat="item in list" ng-click="select(item)" ng-class="{ selected: isSelected(item) }">
<span>{{property !== undefined ? item[property] : item}}</span>
<i class="fa fa-check"></i>
</div>
</div>
</div>
Below is the angularjs directive
App.directive("dropdown", function ($rootScope) {
return {
restrict: "E",
templateUrl: "/app/dropdownTemplate.html",
scope: {
placeholder: "#",
list: "=",
selected: "=",
property: "#"
},
link: function (scope) {
scope.listVisible = false;
scope.isPlaceholder = true;
scope.select = function (item) {
scope.isPlaceholder = false;
scope.selected = item;
};
scope.isSelected = function (item) {
return item[scope.property] === scope.selected[scope.property];
};
scope.show = function () {
scope.listVisible = true;
};
$rootScope.$on("documentClicked", function (inner, target) {
console.log($(target[0]).is(".dropdown-display.clicked") || $(target[0]).parents(".dropdown-display.clicked").length > 0);
if (!$(target[0]).is(".dropdown-display.clicked") && !$(target[0]).parents(".dropdown-display.clicked").length > 0)
scope.$apply(function () {
scope.listVisible = false;
});
});
scope.$watch("selected", function (value) {
scope.isPlaceholder = scope.selected[scope.property] === undefined;
scope.display = scope.selected[scope.property];
});
}
}
});
I am trying to get the list of countries from another controller whose function is as follows,
addressService.getCountries().success(function (response) {
angular.copy(response, $scope.list);
}
How do I bind the values from the controller to my directive when the page loads?
EDIT: What do I do as the directive loads before the function addressService.getCountries() gets called?
you can make a factory that will be useful throughout project to make to make a variable accessible whenever and wherever, in any controller or in any directive you want to use that variable you can easily access
this is how we can make factory,
(function() {
"use strict";
angular.module('dataModule',[])
.factory('datafactory',function(){
return {
credentials : {},
};
});
})();
After making this factory you can inject this module in your module and this factory in your controller
whenever you want you can use this like
addressService.getCountries().success(function (response) {
datafactory.country = response
}
in your controller
$scope.myvar =datafactory.country
in future you use this factory for any such variable that will be accessible everywhere for example you want to store list of state globally
datafactory.state =["abc","def","xyz"]
I am trying to create a angular tree directive, here is the codes :
//** Tree constructor
var Tree = function() {
return {
restrict: 'EA',
replace: true,
template: "<ul>" +
"<li ng-repeat=\"node in node.children\">" +
"<a ng-click=\"selectNode(node)\" ng-class=\"{selected: isSelected(node)}\">" +
"{{node.name}}" +
"</a>" +
"<tree-children></tree-children>" +
"</li>" +
"</ul>",
scope: {
treeData: '='
},
controller: function($scope) {
//** Selected Node
$scope.selectedNode = null;
//** Node on click
$scope.selectNode = function(node) {
if ($scope.selectedNode !== node) {
$scope.selectedNode = node;
} else {
$scope.selectedNode = null;
}
};
$scope.isSelected = function(node) {
return (node === $scope.selectedNode);
}
},
link: function(scope, elem, attrs) {
//** Watch
scope.$watch('treeData', function(data) {
if (angular.isArray(data)) {
scope.node = {};
scope.node.children = data;
} else {
//***********
}
});
}
}
}
//** Tree children constructor
var TreeChildren = function($compile) {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
var childScope = scope.$new(),
template = '<tree tree-data="node.children"></tree>',
content = $compile(template)(childScope);
//** Append
elem.append(content);
}
};
};
TreeChildren.$inject = ['$compile'];
//** Angular Module
angular
.module('app', [])
.directive('tree', Tree)
.directive('treeChildren', TreeChildren)
.controller('treeCtrl', ['$scope', function($scope) {
$scope.treeData = [
{
name: 'Root',
children: [
{
name: 'Node-1',
children: [
{ name: 'Node-1-1'},
{ name: 'Node-1-2'},
{ name: 'node-1-3'}
]
},
{
name: 'Node-2',
children: [
{ name: 'Node-2-1'}
]
}
]
}
];
}]);
The Plunker link
I have got the problem to set up $scope.selectedNode to be a Global one, now if click on the tree node, the css style doesn't look right, as $scope.selectedNode only affect on it's own scope within the treeChildren directive.
How do I do the scope inheritance from the main directive scope? as I want every node click will access the Global $scope.selectedNode.
I have done some reading on Understanding Scopes but still confuse.
Hope I do explain clearly as my poor english
There are a few things wrong with your code. Instead of going through them, I suggest trying using the alias syntax on your controller.
It will simplify your code and probably clarify what you're trying to do.
The alias syntax avoids injecting $scope directly and makes clearer which controller one is using.
Check this awesome explanation out.
I hope it helps.
I am trying to update testVar1 the ng-model attr for the input. The value succesfully gets
$scope.testVar1 = menuElements[$scope.element.id].value;
But when i change the value of
menuElements[$scope.element.id].value;
I want testVar1 to update along with its input view
Is this possible? if so what am i doing wrong? I made a function below to try and hard set the code to val = 2 but it was not succesful it seems that the scope variables only update when you build the page(at least the way ive written it)
HTML:
<div class="well">
<label for="{{element.id}}">{{element.info}}:</label>
<input class="ui-slider" type="range" ng-model="testVar1" ng-change="changeValue(element.id)" name="{{element.id}}" min="{{element.min}}" max="{{element.max}}" id="{{element.id}}"/>
<button ng-click="setTestValue()">Test</button>
</div>
Directive and controller
cordovaAngular.directive('myCustomer', function () {
return {
restrict: 'A',
scope: {
element: '=',
elementArray: '='
},
templateUrl: elementURL,
controller: function ($scope) {
var test = JSON.stringify($scope.elementArray);
$scope.selectedOption = "Success"
$scope.testVar1 = menuElements[$scope.element.id].value;
console.log($scope.testVar1);
console.log($scope.element.id);
$scope.changeOption = function (selectedItem) {
$scope.selectedOption = selectedItem;
// alert(1);
}
$scope.changeValue = function (id) {
menuElements[id].onChange();
}
$scope.setTestValue = function () {
menuElements[$scope.element.id].value = 2;
$scope.testVar1.
console.log($scope.testVar1);
}
}
};
});
I think you can use $watch
Assign menuElements to a $scopevariable and add a $watch listener to it.
$scope.$watch('menuElements', function(newVal, oldVal){
// When menuElementes change, update testVar1 here
$scope.testVar1 = menuElements[$scope.element.id].value;
}, true);
The AngularJS docs for $watch
You need menuElements to be part of the scope in order to be able to watch changes in it. Since your directive has isolated scope, it should be in the scope of your directive. Here is an example of doing it:
HTML
<body ng-controller="ctrl" id="ctrl">
<ul>
<li ng-repeat="element in data.elementArray">{{element.id}} - {{data.menuElements[element.id].value}}</li>
</ul>
<div my-customer="" element="data.element" element-array="data.elementArray" menu-elements="data.menuElements"></div>
</body>
JavaScript
angular.module('app', []).
controller('ctrl', ['$scope', function($scope) {
$scope.data = {
elementArray: [{
id: 'el1',
info: 'Element Info 1',
min: 0,
max: 9
}, {
id: 'el2',
info: 'Element Info 2',
min: 10,
max: 19
}],
menuElements: {
'el1': {
value: 1
},
'el2': {
value: 15
}
}
};
$scope.data.element = $scope.data.elementArray[0];
}]).
directive('myCustomer', function() {
return {
template: '<div class="well">' +
'<label for="{{element.id}}">{{element.info}}:</label>' +
'<input class="ui-slider" type="range" ng-model="testVar1" ng-change="changeValue(element.id)" name="{{element.id}}" min="{{element.min}}" max="{{element.max}}" id="{{element.id}}"/>' +
'<button ng-click="setTestValue()">Test</button>' +
'</div>',
scope: {
element: '=',
elementArray: '=',
menuElements: '=' // <= add menuElements to scope
},
controller: ['$scope', function($scope) {
$scope.setTestValue = function() {
$scope.menuElements[$scope.element.id].value = 5;
}
}],
link: function(scope, element, attr) {
scope.$watch(function() { // <= Watch changes of scope.menuElements[scope.element.id].value
return scope.menuElements[scope.element.id].value;
}, function(value) {
scope.testVar1 = value;
});
}
}
});
Plunker: http://plnkr.co/edit/FLl6pLBdCWAfTbvGSBxQ?p=preview
Edit:
If you need to modify scope from outside of Angular, you can still do it, by fetching scope of DOM element related to that scope:
function setValue() {
var scope = angular.element(document.getElementById('ctrl')).scope();
scope.$apply(function() {
scope.data.menuElements[scope.data.element.id].value = 7;
});
}
Plunker: http://plnkr.co/edit/LXwJEtCIxVNgAb5AdJM6?p=preview
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