I have created a directive which should be able to call a function in a controller and use a variable in controller and directive.
I can not figure out how to call the callback.
I can not figure out to enable two way data binding on my directive scope variable.
Here is the plnk: http://plnkr.co/edit/T1bMYUnkPeZmHHd05SCI?p=preview
html
<!DOCTYPE html>
<html data-ng-app="App">
<head>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body data-ng-controller="BodyCtrl">
<h1>{{title}}</h1>
<div class="container">
<div class="dateselector" data-ng-select="select" data-ng-refresh="refresh()"></div>
</div>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.13/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.13/angular-route.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="script.js"></script>
</body>
</html>
html template
<div class="row">
<div class="col-md-3 col-sm-3">
<select class="form-control" ng-model="select" ng-options="p for p in possibilities"></select>
</div>
<div class="col-md-3 col-sm-3">
<button type="button" class="btn btn-default">Refresh</button>
</div>
</div>
javascript
var app = angular.module('App', ['ui.select']);
app.controller('BodyCtrl', ['$scope', function($scope) {
$scope.title = 'Select Directive';
$scope.select = 1;
$scope.refresh = function() {
alert("Refresh in Controller! " + $scope.select);
};
}]);
// Module
angular.module('ui.select', [])
.directive('dateselector', ['$parse', function($parse) {
var link = function ($scope, $element, $attributes) {
$scope.possibilities = [1,2,3,4,5,6];
$element.find('button').bind('click', function() {
alert('Refresh in directive!');
// How to call callback?
$scope.refresh;
});
};
return {
restrict: 'EC',
replace: true,
templateUrl: 'template.html',
scope: {
select: "=",
refresh: "&"
},
link: link
};
}]);
The basic problem is that your directive expects to see and attribute of the form some-name or data-some-name, but you specify one like this: data-ng-some-name.
Additionally, the recommended way to bind a callback to a button's click event is using ngClick.
<!-- In the VIEW -->
<div class="dateselector" data-select="select" data-refresh="refresh()"></div>
<!-- In the TEMPLATE -->
<button ... ng-click="refresh()">Refresh</button>
See, also, this modified demo.
Related
I have a directive for Opentoke Library but it's not working when I am using the ng-if, the reason of using ng-if is for IOS devices webrtc is not supported so it's showing alert after DOM load.
<div class="opentok" ng-if="!isMobileView">
<open-tok-archive></open-tok-archive>
</div>
click me
<div class="opentok" ng-if="!isMobileView">
<open-toke-screen-share></open-toke-screen-share>
</div>
without ng-if every thing is working fine.
Direcitve
'use strict';
var session, apiKey, publisher, openTokToken, archiveID;
angular.module('app')
.directive('openTokArchiv', [function () {
return {
restrict: 'EA',
templateUrl: 'views/pages/openTokArchive.html',
controller: function (OpenTokService, OTSession, $window, $rootScope, $scope, $routeParams, $cookieStore) {
$scope.myMethod = function (){
console.log("---------not-- working ---------")
}
};
}]);
Use ng-show/ng-hide instead of ng-if.
EDITS
<div class="opentok" ng-if="!isMobileView">
<open-tok-archive></open-tok-archive>
</div>
Have a look at this plunker Demo link
Try this without ng-if #working
<!DOCTYPE html>
<html>
<head>
<script data-require="angularjs#1.5.8" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="app" ng-controller="myCtrl" ng-init="variables">
<div class="opentok">
<open-tok-archive></open-tok-archive>
</div>
<button type="button" ng-click="myMethod()">Toggle</button>
</body>
</html>
With ng-if it is not working
<body ng-app="app" ng-controller="myCtrl" ng-init="variables">
<div class="opentok" ng-if="!isMobileView">
<open-tok-archive></open-tok-archive>
</div>
<button type="button" ng-click="myMethod()">Toggle</button>
</body>
I am new for angularjs here i created some sample for date-picker, which is working fine. I want to create a directive for this sample.. i tried its working but after selected the date it show format is not define...
for this sample i need a directive.. any of one help me on this...
thanks
var app = angular.module('myapp', ['ng-bootstrap-datepicker']);
app.controller('AppCtrl', function ($scope) {
$scope.datepickerOptions = {
format: 'yyyy-mm-dd',
language: 'en',
autoclose: true,
weekStart: 0
};
$scope.date = '2000-03-12'
});
var appboot = angular.bootstrap(document, ['myapp']);
<link href="https://rawgit.com/cletourneau/angular-bootstrap-datepicker/master/dist/angular-bootstrap-datepicker.css" rel="stylesheet"/>
<link href="http://netdna.bootstrapcdn.com/bootstrap/2.0.4/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://code.jquery.com/jquery-2.0.2.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/2.0.4/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<script src="https://rawgithub.com/cletourneau/angular-bootstrap-datepicker/master/dist/angular-bootstrap-datepicker.js" charset="utf-8"></script>
<div ng-app="myapp" ng-controller="AppCtrl">
<input id="datepicker" type="text" data-ng-datepicker data-ng-options="datepickerOptions" data-ng-model="date">
<input id="datepickerMirror" type="text" data-ng-model="date">
</div>
If you can use a more modern datepicker (along with its dependencies on a new AngularJS & Bootstrap), below is an example of a very simple directive called my-datepicker, which just takes a date attribute as its model and wraps the uib-datepicker-popup functionality.
angular.module('myApp', ['ui.bootstrap'])
.directive('myDatepicker', function() {
return {
restrict: 'E',
scope: {
date: '='
},
templateUrl: 'partials/my-datepicker.html',
link: function(scope, element, attrs) {
scope.status = {
opened: false
};
scope.open = function(event) {
scope.status.opened = true;
};
}
};
})
.controller('AppCtrl', ['$scope', function ($scope) {
$scope.date = '2000-03-12';
}]);
.input-group {
width: 200px;
}
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.js"></script>
<div ng-app="myApp" ng-controller="AppCtrl">
<script type="text/ng-template" id="partials/my-datepicker.html">
<div class="input-group">
<input class="form-control" type="text" uib-datepicker-popup ng-model="date"
is-open="status.opened">
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open($event)">
<span class="glyphicon glyphicon-calendar"></span>
</button>
</span>
</div>
</script>
<div class="container">
<my-datepicker date="date"></my-datepicker>
</div>
<input id="datepickerMirror" type="text" ng-model="date">
</div>
Note that the date model gets passed into your directive will be used as the ng-model for the actual uib-datepicker-popup; you can confirm this by selecting a date via the directive and seeing that the other input (outside of your directive) gets updated.
You can also move your directive's template (partials/my-datepicker.html) into its own file, rather than embedding it as a text/ng-template.
EDIT #2
As requested, below is an example using the ng-bootstrap-datepicker directive. Note the use of controller: ... instead of link: ... to set the datepickerOptions model; this is to make sure the update to our directive's scope is available when linking occurs (i.e. when the actual ng-bootstrap-datepicker directive is being initialized):
angular.module('myapp', ['ng-bootstrap-datepicker'])
.directive('myDatepicker', function() {
return {
restrict: 'E',
template: '<input type="text" ng-datepicker ng-options="datepickerOptions" ng-model="date">',
scope: {
date: '='
},
controller: function($scope) {
$scope.datepickerOptions = {
format: 'yyyy-mm-dd',
language: 'en',
autoclose: true,
weekStart: 0
};
}
};
})
.controller('AppCtrl', ['$scope', function ($scope) {
$scope.date = '2000-03-12'
}]);
angular.bootstrap(document, ['myapp']);
<link href="https://rawgit.com/cletourneau/angular-bootstrap-datepicker/master/dist/angular-bootstrap-datepicker.css" rel="stylesheet"/>
<link href="http://netdna.bootstrapcdn.com/bootstrap/2.0.4/css/bootstrap.min.css" rel="stylesheet"/>
<script src="http://code.jquery.com/jquery-2.0.2.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/2.0.4/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<script src="https://rawgithub.com/cletourneau/angular-bootstrap-datepicker/master/dist/angular-bootstrap-datepicker.js" charset="utf-8"></script>
<div ng-app="myapp" ng-controller="AppCtrl">
<my-datepicker date="date"></my-datepicker>
<input id="datepickerMirror" type="text" data-ng-model="date">
</div>
The angular-bootstrap-datepicker directive doesn't look to be compatible with the latest AngularJS/Bootstrap versions, so the example above uses the same from the OP's snippet.
This directive fires when ng-repeat finishes using scope.$last:
simpleSearchApp.directive('afterResults', function($document) {
return function(scope, element, attrs) {
if (scope.$last){
scope.windowHeight = $document[0].body.clientHeight;
}
};
});
I'm trying to update $scope.windowHeight with a new value but I can't access $scope inside the directive.
My ng-repeat HTML with directive:
<div ng-show="items" class="ng-cloak" ng-repeat="item in items" after-results>
{{item}}
</div>
Honestly saying I have also not understand why it's not updating. But the the alternate approach to update variable in controller is to define a function wich update the variable and call that function in controller from directive. Please take a look at the following example it might help you.
angular.module('app',[]).controller('MyController',['$scope',function($scope){
$scope.windowHeight = 0;
$scope.updateWindowHeight = function(height){
$scope.windowHeight = height;
}
}])
.directive('afterResults', function($document) {
return function(scope, element, attrs) {
if (scope.$last){
scope.windowHeight = $document[0].body.clientHeight;
scope.updateWindowHeight( scope.windowHeight);//calling function in controller
}
};
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#1.4.1" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MyController">
<div class="ng-cloak" ng-repeat="item in [1,2,3,4,5]" after-results="updateWindowHeight()">
{{item}}
</div>
<hr/>{{ "$scope.windowHeight ="+windowHeight}}
</body>
</html>
I am trying to load a HTML template when a link is clicked. I have made a directive that contains templateUrl which loads a HTML file. I am calling a function when a link is clicked that appends a div with our custom directive "myCustomer" to a div already in index.html. whatever i have done so far is shown below, but it doesn't work.
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-example12-production</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.1/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="docsTemplateUrlDirective">
<div ng-controller="Controller">
show
<div id="d"></div>
</div>
</body>
</html>
script.js
(function(angular) {
'use strict';
angular.module('docsTemplateUrlDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.showdiv = function(){
$("#d").append("<div my-Customer></div>");
};
}])
.directive('myCustomer', function() {
return {
templateUrl: 'my-customer.html'
};
});
})(window.angular);
my-customer.html
<p>DIV CONTENT</p>
Here is the link i was testing this code here
This is because the angular doesn't bind the directives if you append content like this,
you need to $compile service to do this and this will bind the directives against your $scope
so controller like,
.controller('Controller', ['$scope', '$compile', function($scope, $compile) {
$scope.showdiv = function(){
var compiledeHTML = $compile("<div my-Customer></div>")($scope);
$("#d").append(compiledeHTML);
};
}])
here is the DEMO
OR good to do like this,
use ng-if to create or removing element from html,
try this code
Controller,
....
$scope.anableCustomerDirective = false;
$scope.showdiv = function(){
$scope.anableCustomerDirective = true;
};
HTML
<body ng-app="docsTemplateUrlDirective">
<div ng-controller="Controller">
show
<div id="d">
<div my-Customer ng-if='anableCustomerDirective'></div>
</div>
</div>
</body>
Suggestion
if your main intention is to place a html content after the click, then you can use ng-include here and it will much cleaner and no need of a another directive.
<div id="d">
<div ng-include="templateURL"></div>
</div>
$scope.showdiv = function(){
$scope.templateURL = 'my-customer.html';
};
find the DEMO
Seems like directive is only meant to load template from it.I'd suggest you to use ng-include directive then
Markup
show
<div id="d"></div>
<div ng-include="showDiv ? 'my-customer.html': ''">
The most common way is to use $compile. More info: Dynamically add directive in AngularJS
Then your controller may look like this:
angular.module('docsTemplateUrlDirective', [])
.controller('Controller', ['$scope', '$compile', function($scope, $compile) {
$scope.showdiv = function(){
var el = $compile( "<div my-customer></div>" )( $scope );
$('#d').append( el );
};
}]);
Note that the directive invokation should look like this: <div my-customer>, not <div my-Customer></div> as you have in your code.
when you do it manually with append you actually do not run $apply or $digest so the directive is not run,
can you try to do it with ng-show or ng-if ... e.g
<body ng-app="docsTemplateUrlDirective">
<div ng-controller="Controller">
show
<div my-customer ng-if="showdiv"></div>
<div id="d"></div>
</div>
</body>
this way angular runs the $apply and the directive will be rendered.
I use ui-keypress directive in input fields to apply the function newline() that creates a new input field under the current(focused) one. It works ok, but I want to update this function so the focus jumps down to the newly created field.
Here is my index.html:
<!doctype html>
<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.min.js">
</script>
<script src="script.js"></script>
<script src="keypress.js"></script>
</head>
<body ng-controller="TextCtrl">
<div ng-repeat="task in tasks track by $index">
<input type="text" class="form-control" ng-model="task.text" ui-keypress="{13:'newline($index+1)'}" >
</div>
</body>
</html>
And this is script.js:
var myAppModule = angular.module('myApp', ['ui.keypress']);
myAppModule.controller('TextCtrl',function($scope){
var emptytask = '';
var tasks=[{text:'chart'}];
$scope.tasks = tasks;
$scope.newline = function(index){
$scope.tasks.splice(index,0,{text:emptytask});
};
});
Can you try something like this in directive
.directive('focusOnLoad', function () {
return {
restrict: 'E',
link: function (scope, element, attrs) {
$timeout(function() {
element.find('input').focus()
},0);
}
}
}
On HTML do
<div ng-repeat="task in tasks track by $index" focus-on-load>
In controller just add the new task.