Why my angular directive doesn't work? - angularjs

I have a directive that is triggered when clicking on a button. The function inside the directive simply has to change the property value of the field. So what I try to do is to change from 'popover-trigger="blur"' to 'popover-trigger="none"'.
Here is my plunkr: http://plnkr.co/edit/L81fQgi7j1dEtf1QAZJ2?p=preview
or the code is here:
var app = angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
app.controller('PopoverDemoCtrl', function ($scope) {
$scope.dynamicPopover = {
content: 'Hello, World!',
templateUrl: 'myPopoverTemplate.html',
title: 'Title'
};
$scope.label = "Please click";
$scope.message = "ON FOCUS trigger a tooltip";
$scope.htmlPopover = "myPopoverTemplate.html";
});
app.directive("changeTrigger", function($compile){
return{
restrict: 'A',
link: function(scope, elm, attrs)
{
elm.bind('click', function(){
var t = document.getElementsByClassName('f')[0].setAttribute('popover-trigger', 'none');
$compile(t);
console.log("Click works");
});
}
}
});
html
<div ng-controller="PopoverDemoCtrl">
<br><br><br>
<p>{{message}}</p>
<input class="f" type="text" value="Click me!" uib-popover-template="htmlPopover" popover-trigger="focus" popover-popup-close-delay="1000" popover-placement="right" required>
<test-directive></test-directive>
<script type="text/ng-template" id="myPopoverTemplate.html">
<div>
<p>Click the button to stop triggering tooltip!</p>
<button change-trigger><b style="color: red">Stop tooltip</b></button>
<div class="label label-success">page</div>
</div>
</script>
</div>

You can't reconfigure the angular-bootstrap Popup element by changing uib-popup-* parameters; but you can bind a scope variable to popup-enable attribute to be able to switch the popup on/off. Add:
<input ... uib-popover-template="htmlPopover" popover-enable="enable" ...>
and
$scope.enable = true;
The problem here is that your button and the input box have different scopes. But you can fix this by retrieving the scope of the field:
var t = document.getElementsByClassName('f')[0];
var scope_ = angular.element(t).scope();
Of course, you need to use $scope.$apply for the scope to correctly handle two-way data binding:
scope_.$apply(function () {
scope_.enable = false;
});
Working Plunkr.

Related

Image is not changing even i changed image

In angularjs if i change or remove image it does not make any changes. After refreshing the page it show the changed image.I am using following line to remove image
jQuery
$('#profile_image').val('')
This Sample is basic if you want to know more about AngularJs click on link
var app = angular.module("app", []);
app.controller("ctrl", [
"$scope",
function($scope) {
$scope.imgShow = true;
$scope.imgSrc = "https://www.gravatar.com/avatar/75025ad9a8cfdaa5772545e6e8f41133?s=32&d=identicon&r=PG&f=1";
$scope.display = function() {
$scope.imgShow = true;
$scope.imgSrc = "https://www.gravatar.com/avatar/75025ad9a8cfdaa5772545e6e8f41133?s=32&d=identicon&r=PG&f=1";
}
$scope.change = function() {
$scope.imgSrc = "https://www.gravatar.com/avatar/fccd71b79b3571b459cdfe40e7bf5dd8?s=32&d=identicon&r=PG&f=1";
}
$scope.remove = function() {
$scope.imgShow = false;
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<img ng-src="{{imgSrc}}" ng-show="imgShow">
<hr/>
<button ng-click="display()" ng-hide="imgShow">display image</button>
<button ng-click="change()">change image</button>
<button ng-click="remove()">remove image</button>
</div>
If you want to manipulate the DOM in AngularJS you should use directives for this purpose.
You should avoid using jquery inside of your controllers and simply work with your model. Below is fileUpload directive that could help you to work with <input type="file"> in a more angularjs-way:
angular.module('myApp', [])
.controller('TestController', ['$scope', function ($scope) {
var ctrl = this;
ctrl.imageFile = null;
ctrl.clearFile = clearFile;
function clearFile(){
ctrl.imageFile = null;
}
$scope.$ctrl = ctrl;
}])
.directive('fileUpload', [function () {
return {
require: "ngModel",
restrict: 'A',
link: function ($scope, el, attrs, ngModel) {
function onChange (event) {
//update bindings with $applyAsync
$scope.$applyAsync(function(){
ngModel.$setViewValue(event.target.files[0]);
});
}
//change event handler
el.on('change', onChange);
//set up a $watch for the ngModel.$viewValue
$scope.$watch(function () {
return ngModel.$viewValue;
}, function (value) {
//clear input value if model was cleared
if (!value) {
el.val("");
}
});
//remove change event handler on $destroy
$scope.$on('$destroy', function(){
el.off('change', onChange);
});
}
};
}]);
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.3.20/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="TestController">
<input type="file" file-upload ng-model="$ctrl.imageFile" />
<input type="button" ng-click="$ctrl.clearFile()" value="Reset" />
<div ng-if="$ctrl.imageFile">
{{$ctrl.imageFile.name}}<br />
{{$ctrl.imageFile.size}} byte(s)<br/>
{{$ctrl.imageFile.type}}
</div>
</div>
</div>
UPDATE: Also take a look at this useful reading.

Bootstrap DateTimePicker with AngularJS: Passing directive ngModel value to controller

I am trying to get angular bootstrap datetimepicker input value using a custom directive like shown below. I am able to get the value in directive. How can i access this directive scope value in angular controller.
HTML
<div class='input-group date' id='datetimepickerId' datetimez ng-model="dueDate" >
<input type='text' class="form-control" />
</div>
Controller
App.directive('datetimez', function(){
return {
require: '?ngModel',
restrict: 'A',
link: function(scope, element, attrs, ngModel){
if(!ngModel) return;
ngModel.$render = function(){
element.find('#datetimepickerId').val( ngModel.$viewValue || '' );
};
element.datetimepicker({
format : 'YYYY-MM-DD HH:mm:ss'
});
element.on('dp.change', function(){
scope.$apply(read);
});
read();
function read() {
var value = element.find('#datetimepickerId').val();
ngModel.$setViewValue(value);
console.log(scope.dueDate);
}
}
};
});
App.controller('myController', ['$scope', function($scope) {
console.log($scope.dueDate);
}]);
Log inside the directive prints value successfully. But log inside controller does not.
Here you go.
I checked the documentation of the bootstrap datetimepicker and come to know there are two implementation.
One with a icon to click and show the datetimepicker
Another one just with a textbox without a icon
For the first one, you have to use the parent div to initiate the plugin and for the second option, you have to use the textbox to initiate the plugin
You have used the second option but used the parent div to initiate the plugin with a directive.
Also, div elements won't support the ngModel, hence directive should be used with the input element.
I have extended your directive to handle both scenarios and also the date format and other options can be passed from the controller.
You can give a try with the below working snippet.
var App = angular.module('App', []);
App.directive('datetimez', function(){
return {
require: '?ngModel',
restrict: 'A',
link: function(scope, element, attrs, ngModel){
if(!ngModel) return;
ngModel.$render = function(){
element.val( ngModel.$viewValue || '' );
};
function read() {
var value = element.val();
ngModel.$setViewValue(value);
//console.log(scope.dueDate);
}
var options = scope.$eval(attrs.datetimez) || {};
if(element.next().is('.input-group-addon')) {
var parentElm = $(element).parent();
parentElm.datetimepicker(options);
parentElm.on('dp.change', function(){
scope.$apply(read);
});
} else {
element.datetimepicker(options);
element.on('dp.change', function(){
scope.$apply(read);
});
}
read();
}
};
});
App.controller('myController', ['$scope', function($scope) {
$scope.datePickerOptions = {
format : 'YYYY-MM-DD HH:mm:ss'
};
$scope.$watch('dueDate1', function(){
console.log($scope.dueDate1);
});
$scope.$watch('dueDate2', function(){
console.log($scope.dueDate2);
});
}]);
angular.bootstrap(document, ['App']);
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.43/css/bootstrap-datetimepicker.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.16.0/moment.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.43/js/bootstrap-datetimepicker.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container" ng-controller="myController">
<div class="row">
<div class='col-md-6'>
<div class="form-group">
<div class='input-group date' id='datetimepicker1'>
<input type='text' class="form-control" datetimez="datePickerOptions" ng-model="dueDate1" />
</div>
</div>
</div>
</div>
<div class="row">
<div class='col-md-6'>
<div class="form-group">
<div class='input-group date' id='datetimepicker1'>
<input type='text' class="form-control" datetimez="datePickerOptions" ng-model="dueDate2" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
</div>
</div>

Focus on textbox when radiobutton is selected in AngularJS

can someone please give me an idea on how will i set focus on my textbox when I click the radiobutton assigned to it? Im using angular js. Thanks for any idea
I created example for you.
HTML:
<body ng-app="scopeExample">
<div ng-controller="MyController">
<div ng-repeat='item in mas'>
<input type="radio" name='somename' ng-model="item.select" value="true" ng-click='clear(item)'>
<input type='text' focus='item.select'/>
<br>
</div>
</div>
</body>
Javascript:
angular.module('scopeExample', [])
.controller('MyController', ['$scope', function($scope) {
$scope.mas=[
{id:1,select:false},
{id:2,select:false},
{id:3,select:false},
{id:4,select:false}
];
$scope.clear = function(item){
$scope.mas.forEach(function(x){
if(x != item)
x.select=false;
});
}
}]).directive('focus',['$timeout', '$parse', function($timeout, $parse){
return {
link:function (scope, element, attrs) {
var model = $parse(attrs['focus']);
scope.$watch(model, function (value) {
if (eval(value))
$timeout(function () {
element[0].focus();
});
});
}
}
}]);
I will provide you pseudo code which you can alter on the basis of your needs. For now, the code has one radio button which when selected will focus on the input element. However, you can achieve those on list, on checkbox as per your need.
HTML:
<div ng-controller="MyCtrl">
<input type="radio" ng-model="focusRadio" value=0>
<input ng-model="name" focus>
</div>
Script:
var myApp = angular.module('myApp',[]);
myApp.directive('focus', function() {
return function(scope, element) {
scope.$watch('focusRadio',
function (newValue) {
newValue && element[0].focus()
})
}
});
function MyCtrl($scope) {}
Here is the plunker: http://plnkr.co/edit/ABHCRIm95EyNUI8nWczh?p=preview . Change the input type to checkbox to better know about the functionality.

How to apped a `directive` by click

Say, I have multiple directives, on click how can i add the "directive" what i want to "popup". i have number of scenario, but using only one pop-up for all. whenever the appropiate element is clicked, using the same pop-up, i would like to update the other 'directives'
for sample, i created only one. click on the red bordered title
here is my code :
<div ng-controller="main">
{{name}}
<div class="info" ng-click="popIt()">
<info-board></info-board>
</div>
<div class="popup" ng-if="show" ng-click="popIt()">
//add directive dynamically - how?
</div>
</div>
</body>
<script type="text/ng-template" id="modalPopup.html">
<div class='ng-modal'>
some information here.
</div>
</script>
js:
var myApp = angular.module("myApp", []);
myApp.controller("main", function($scope) {
$scope.name = "Mo!";
$scope.show = false;
$scope.popIt = function (show) {
$scope.show = !$scope.show;
}
})
myApp.directive("infoBoard", function() {
return {
replace : true,
templateUrl: "modalPopup.html",
scope : {},
link : function (scope, element, attrs) {
element.append("Hi there!")
}
}
})
Demo Onlie

Controller $scope property does not change with expression in transcluded content

The problem is that when you have transcluded content which contains an expression as an attribute of ng-click for example, the change does not occur in the scope of the parent controller as you can see in this fiddle:
http://jsfiddle.net/vt7rmqya/
Nothing happens when you click hide box inside of transcluded content.
<div ng-controller="myCtrl">
<panel ng-show='showBox'>
<div class='box'>
{{name}}
<br>
<button ng-click='showBox = false'>hide box button inside of transcluded content</button>
</div>
</panel>
<br>
Here, the expression in ng-click has no effect on the $scope.showBox in the controller but you would think that it would because the scope of the transcluded content should be the same as the controller scope, right?
BaseApp = angular.module('BaseApp', []);
BaseApp.controller('myCtrl', function($scope) {
$scope.name = 'bill jones';
$scope.showBox = true;
});
BaseApp.directive('panel', function() {
return {
restrict: 'E',
template: '<div>header<br><div ng-transclude></div></div>',
transclude: true,
}
})
I realized that the solution is simply to set the ng-click attribute to a function in the controller instead of an expression like so:
BaseApp.controller('myCtrl', function($scope) {
$scope.name = 'bill jones';
$scope.showBox = true;
$scope.hideBox = function() {
$scope.showBox = false;
}
});
<panel ng-show='showBox'>
<div class='box'>
{{name}}
<br>
<button ng-click='hideBox()'>hide box button inside of transcluded content</button>
</div>
</panel>
Here's the working fiddle:
http://jsfiddle.net/75f2hgph/

Resources