$watch isn't called after one directive is initiated in AngularJS - javascript

I am trying call up to do focus of a element in directive of modal.
After the directive is called the focus-me directive is called only first time.
I tried adding the focus-me element in dialog directive as shown in the Plunker.
Below are things which I am trying in the directive.
Show the Modal dialog box [working]
After the dialog box is shown i am trying to focus a specfic element in the dialog box [For which i added watch element in focus-me directive]
The Focus is happening only for the first time.
Plunker
Please help with,how to trigger the watch element on the directive for the above Plunker. Thanks a lot.
Below is the directive code for the focus and dialog which i am currently using.`
app.directive('focusMe', function($timeout, $parse) {
return {
link: function(scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function(value) {
console.log('value=',value);
if(value === true) {
$timeout(function() {
element[0].select();
element[0].focus();
});
}
});
element.bind('blur', function() {
console.log('blur')
scope.$apply(model.assign(scope, false));
})
}
};
}).directive('modalDialog', function(){
return {
restrict: 'AE',
scope: {
show: '=',
focusDesign:'=focusDesign'
},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
if (attrs.focusDesigniso)
scope.focusDesigniso=attrs.focusDesigniso;
scope.hideModal = function(focusDesign) {
scope.show = false;
focusDesigniso=false;
//$scope.focusDesign=false;
};
scope.hideModalC = function() {
alert("I m in hide");
scope.show = false;
};
},
template: "<div class='ng-modal' ng-show='show'><div class='ng-modal-overlay' ng-click='hideModal(focusDesign)' ng-model='focusDesign'></div><div class='ng-modal-dialog' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal(focusDesign)' ng-model='focusDesign'>X</div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"
};
});

I got solution for the problem in the directive.
The $scope.apply i was applying it model instead i should i used for the element in focus.
The updated the directive of focus i have copied below with working Plunker
app.directive('focusMe', function($timeout, $parse) {
return {
link: function(scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function(value) {
console.log('value=',value);
if(value === true) {
$timeout(function() {
element[0].select();
element[0].focus();
});
}
});
element.bind('blur', function() {
scope.$apply(function()
{
attrs.focusMe=!attrs.focusMe;
})
})
}
};
});
Working Plunker

Related

AngularJS =?bind not updating

I've lost my bearings with regards to why I can't pass updates to my directives.
What I'm trying to accomplish with the following piece of code is to be able to set focus on by pressing a button. The problem is however that the "focus" binding on drInput only ever is set when the directive have loaded when it should change whenever it changes in drWrap. How come and how do I get around this?
And now, ladies and gentlemen, I present to you: THE CODE!
<div ng-app="myApp">
<dr-wrap></dr-wrap>
</div>
var myApp = angular.module('myApp', []);
myApp.directive('drWrap', function($timeout) {
return {
scope: {
focus: '=?bind'
},
restrict: 'E',
replace: 'true',
template: '<div><button ng-click="openSearch()">focus</button><dr-input focus="focusSearch" /></div>',
link: function(scope, elem, attr){
scope.openSearch = function(){
$timeout(function(){
scope.focusSearch = true
alert('scope.focusSearch 2 = ' + scope.focusSearch)
}, 1000)
}
}
};
})
.directive('drInput', function() {
return {
scope: {
focus: '=?bind'
},
restrict: 'E',
replace: 'true',
template: '<input type="test" focus-me="{{ focus }}" />',
link: function(scope, elem, attr){
scope.$watch('focus', function(value){
if(value != undefined){
scope.focus = value
alert('scope.focus = ' + scope.focus)
}
})
}
};
})
.directive('focusMe', ['$timeout', function ($timeout) {
return {
link: function (scope, element, attrs) {
attrs.$observe('focusMe', function(value){
if ((value === true) || (value == 'true')) {
$timeout(function () {
element[0].focus()
scroll(element[0])
})
} else {
element[0].blur()
}
})
}
}
}])
And the FIDDLE!
https://jsfiddle.net/L56rdqLp/168/
When you write scope: { focus: '=?bind' }, this means that the attribute name should be bind but not focus, so the template of drWrap should look like:
template: '<div><button ng-click="openSearch()">focus</button><dr-input bind="focusSearch" /></div>'
Add ngBlur event handler to drInput directives input like:
template: '<input type="test" focus-me="{{ focus }}" ng-blur="focus = false"/>',
to change the model to false, when input has lost its focus.
Here is working fiddle.

AngularJS directive multiple selectors

I want to make my directive multiple selectors.
My directive is alerting every tap.
I already wrote this code:
angular
.module('app.directives')
.directive('onTap', someDirective)
.directive('button', someDirective);
someDirective.$inject = ['$ionicGesture'];
function someDirective($ionicGesture) {
return {
restrict: 'EA',
link: link
};
function link($scope, $elem, $attrs) {
$ionicGesture.on('tap', function() {
alert('Tapped!');
}, $elem);
}
}
This code problem is this button for example:
<button on-tap="doSomething()">Do something</button>
Because this button tap will alert twice!
I can even solve if i change the directive:
.directive('someDirective', someDirective);
But it means I have to add it to every button or [onTap] selector.
Any good solution?
You can try this:
function someDirective($ionicGesture) {
var directive = {
restrict: 'EA',
link: link
};
return directive;
function link($scope, $elem, $attrs, ctrls) {
if (directive.name === 'onTap' && $elem.is('button')) {
return;
}
$ionicGesture.on('tap', function() {
alert('Tapped!');
}, $elem);
}
}

Making a simple directive only modal dynamic

So i am a new to angular. Trying to make a simple modal using angular directives only.
The reasons for making this:
No need to use bootstrap
No need for a controller and
Thus no dependency injection
function modalTrigger() {
return {
restrict: 'A',
transclude: true,
link: function(scope, element, attrs) {
scope.show = false;
scope.toggleModal = function() {
console.log(scope);
scope.show = !scope.show;
};
},
template: '<div class="modal-trigger" ng-click="toggleModal()" ng-transclude></div>'
};
}
function modalDialog() {
return {
restrict: 'E',
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
scope.hideModal = function() {
console.log("called hide modal");
scope.show = false;
};
},
template: "<div class='ng-modal' ng-show='show'><div class='modal-backdrop' ng-click='hideModal()'></div><div class='container' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal()'><a href=''>×</a></div><div class='modal-content' ng-transclude></div></div></div>"
};
}
"modal-trigger" directive is used to trigger the "modal-dialog" directive by setting "show" to true. here are the two directives
Right now, if you click any of the triggers, both the modals show up. how do i make the triggers specific to their own modals?
To make things more clear, here is an example on plunker: http://plnkr.co/edit/lNwTy3ddFFBBm2DPHUGA?p=preview
The problem is that both modals observe the same attribute (show) for showing/hiding themselves. To correct this, the show attribute must be scoped for each modal and I propose the following:
Have a controller that defines the 2 show attributes:
app.controller('Ctrl', function($scope) {
$scope.show1 = false;
$scope.show2 = false;
});
And activate it as:
<body ng-app="angularApp" ng-controller="Ctrl as ctrl">
Change the modal trigger to have isolated scope and the show attribute, as follows:
function modalTrigger() {
return {
restrict: 'A',
transclude: true,
link: function(scope, element, attrs) {
scope.toggleModal = function() {
scope.show = !scope.show;
};
},
scope: {
show: '='
},
template: '<div class="modal-trigger" ng-click="toggleModal()" ng-transclude></div>'
};
}
Use it e.g. as:
Waiting List
Change the modal directive to use isolated scope with the show attribute; simply add:
scope: {
show: '='
},
to the directive. Use it as:
<modal-dialog data-modal-name="modal1" show="ctrl.show1">
A forked plunker with the full solution: http://plnkr.co/edit/cJOXju9H3PMjRdUKqVCF?p=preview

Why doesn't the background color of the knob load before click? [Angular.js]

I will keep this simple. You can check this fiddle here jsfiddle. Here when you load the knob, the color of the knob only gets updated on clicking/scrolling over it (the number changes and hence colors up). I have this same problem on my project and was hesitant to ask this as I was skeptic if I could properly make you understand my question. Now that I have this fiddle, I hope you all can see what is happening. I am new to angular.js. Every answer is a learning experience for me. Thanks in advance.
view
<div ng-app="Knob" ng-controller="myCtrl">
<input type="text" ng-model="number" knob class="dial">
</div>
Controller + Directive
var App = angular.module('Knob', []);
App.controller('myCtrl', function($scope) {
$scope.number = 24;
})
App.directive('knob', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
$(element).knob();
}
};
});
I believe it the directive is being called before it has the value.
Wrapping it in a timeout works.
App.directive('knob',['$timeout', function ($timeout) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
$timeout(function () { // You might need this timeout to be sure its run after DOM render.
$(element).knob();
}, 0, false);
}
};
}]);
if anyone still looking to make this work on the latest angular...
angular.module('ui.knob', []).directive('knob', ['$timeout', function ($timeout) {
return {
restrict: 'EA',
replace: true,
template: '<input value="{{ knobData }}"/>',
scope: {
knobData: '=',
knobOptions: '&'
},
link: function ($scope, $element) {
var knobInit = $scope.knobOptions() || {};
knobInit.release = function (newValue) {
$timeout(function () {
$scope.knobData = newValue;
$scope.$apply();
}, 0, false);
};
$scope.$watch('knobData', function (newValue, oldValue) {
if (newValue !== oldValue) {
$($element).val(newValue).change();
}
});
$($element).val($scope.knobData).knob(knobInit);
}
};
}]);
created the fiddle with the working sample...
http://jsfiddle.net/k4yq06yt/

How to use $watch within directive to update class (no jQuery)?

I'm trying to create an app where I poll live data every 10 seconds or so. And if the data changes it should get highlighted in the view. I have successfully managed this, but with a little help from jQuery. I want to do it with a template in angular instead.
This is my controller:
angular.module('myApp.controllers', [])
.controller('MainCtrl', ['$rootScope', 'liveDataPoller', function($rootScope, liveDataPoller) {
$rootScope.liveData = liveDataPoller.getData();
}]);
This is my directive:
angular.module('myApp.directives', []).
directive('liveValue', function() {
return {
restrict: 'A',
scope: {
val: '='
},
link: function(scope, element, attrs) {
scope.$watch('val', function(newValue, oldValue) {
if(newValue && oldValue && (newValue !== oldValue)) {
if(newValue < oldValue) {
element.removeClass("up").addClass("down");
} else {
element.removeClass("down").addClass("up");
}
} else {
element.removeClass("down").removeClass("up");
}
});
}
}
});
This is my view:
<div live-value val="liveData.randomInteger">{{liveData.randomInteger}}</div>
Is it possible to have the add/remove class changed to use transclude and a template instead? Don't really want to mix jQuery in this.
Just let me know if anything is unclear.
Sample demo: http://plnkr.co/edit/uXhOceXYWLLkmRkzxx1h?p=preview
A scope variable can be used to track the new changes and use a two way binding to update the class in the html.
app.directive('liveValue', function() {
return {
restrict: 'E',
replace: true,
scope: {
data: '=', change:'='
},
template: '<div class="{{change}}">The value({{data}}) has gone: {{change}}</div>',
link: function(scope, element, attrs) {
scope.change = '';
scope.$watch('data', function (newValue, oldValue) {
if (newValue == oldValue) {
scope.change='nochange';
}else if(newValue<oldValue){
scope.change='down';
}else{
scope.change='up';
}
});
}
}
});

Categories

Resources