I write a directive to impl ng-disabled because i just can use angularjs which version is 1.1.5,it't not provide ng-disabled,so
tableApp.directive('myDisabled', function($compile) {
return {
restrict: 'A',
replace: true,
scope: {
myDisabled: '='
},
link: function(scope, element, attrs) {
var test = scope.$eval(attrs.myDisabled);
console.log(test);
scope.$watch(attrs.myDisabled, function (test) {
if (test) {
element.attr();
}
else {
element.attr('disabled', 'false');
}
});
}
};
});
the html code:
<html ng-app="tableApp">
<head></head>
<body>
<div ng-controller="TableCtrl">
<input ng-model="page"/>
<button class="btn btn-primary" ng-click="previouspage()" my-disabled="page <=1">上一页</button>
</div>
</body>
</html>
but why i click this button,it can't call the function previouspage()
this is my angularjs code
var tableApp = angular.module('tableApp', [], function ($httpProvider) {
$httpProvider.defaults.headers.post['Content-Type'] =
'application/x-www-form-urlencoded;charset=utf-8';
});
tableApp.directive('myDisabled', function($compile) {
return {
restrict: 'A',
replace: true,
scope: {
myDisabled: '='
},
link: function(scope, element, attrs) {
var test = scope.$eval(attrs.myDisabled);
console.log(test);
scope.$watch(attrs.myDisabled, function (test) {
if (test) {
element.attr();
}
else {
element.attr('disabled', 'false');
}
});
$compile(attrs);
}
};
});
tableApp.controller('TableCtrl', function ($scope, $http) {
$scope.page = 1;
$scope.getCr = function getCr(later) {
var url = '/cms/copyright/find';
var request = $http({
method: 'get',
url: url,
params: {
page_length: 25,
start: ($scope.page - 1) * 25,
s: ''
}
});
request.then(function (data) {
if (data.data.result == 'OK') {
console.log(data.data);
$scope.copyright = data.data;
if (later != undefined) {
later();
}
}
});
};
$scope.nextpage = function nextpage() {
$scope.page += 1;
$scope.getCr();
};
$scope.onepage = function onepage() {
$scope.page = 1;
$scope.getCr();
};
$scope.previouspage = function previouspage() {
$scope.page -= 1;
$scope.getCr();
};
$scope.setPos = function setPos(index, holder_id) {
var pos = window.prompt("请输入排序位置", $scope.copyright.items[index].pos);
console.log(pos);
if (pos != null && pos != "" && parseInt(pos) > 0) {
var a = 'holder_id=' + holder_id + '&pos=' + pos;
$http.post('/cms/copyright/top', a).then(function (data) {
data = data.data;
if (data.result == 'OK') {
$scope.getCr(function () {
$scope.copyright.items[index].change = true;
});
} else {
alert(data.result);
}
});
}
console.log($scope.copyright.items[index]);
};
$scope.getCr();
});
Your problem is related to $scope.
When you are explicitly creating an isolated scope in your directive (using scope: {}) you can't access parent scope directly. If you don't, there is no problem doing so.
So, in short, just change ng-click="previouspage()" to ng-click="$parent.previouspage()" inside your HTML template.
Related plunker here: http://plnkr.co/edit/WRflPF
You could also refactor your directive's link function and remove unnecessary properties. So directive could be:
app.directive('myDisabled', function () {
return {
restrict: 'A',
scope: {
myDisabled: '='
},
link: function(scope, element) {
scope.$watch('myDisabled', function (val) {
element.attr('disabled', val);
});
}
};
});
The problem is the directive scope. You try to access an scope variable from parent scope (your controllers scope)
If you disable the isolate scope for your directive it works
For example:
tableApp.directive('myDisabled', function($compile) {
return {
restrict: 'A',
replace: true,
scope: {
myDisabled: '='
},
link: function(scope, element, attrs) {
var test = scope.$eval(attrs.myDisabled);
console.log(test);
scope.$watch(attrs.myDisabled, function (test) {
if (test) {
element.attr();
}
else {
element.attr('disabled', 'false');
}
});
}
};
});
Related
Edit: I have added the details as well.
I could do with some help with passing the value selected in my directive to my controller $scope.
I have a very basic directive that I want to place within another directive, but the value does not get passed to the controller scope. I get an "undefined" value for my parameter.
However, when I place the little directive anywhere in the view's HTML, and not within the other directive's tags, it works.
This is my new directive:
(function () {
'use strict';
angular.module('portalDashboardApp')
.directive('ogItemsPerPage', function () {
return {
restrict: 'E',
replace: true,
templateUrl: './tpls/ItemsPerPageTemplate.html',
scope: {
perPageCountOptions: [30, 50, 100, "ALL"],
selectedItemsPerPage: '#'
}
};
});
})();
This is the template:
<div>
<div id="DropDownBox">
<label for="ItemsPerpage">Items per Page: </label>
<select ng-change="changePageCount()" ng-model="selectedItemsPerPage" id="ItemsPerpage" ng-options="perPage for perPage in perPageCountOptions"></select>
</div>
</div>
This is the function called in my controller:
$scope.changePageCount = function () {
if ($scope.selectedItemsPerPage === "ALL") {
$scope.perPageCount = -1;
}
else {
$scope.perPageCount = $scope.selectedItemsPerPage;
}
pullSocialData();
}
This is the view where I am placing my <og-items-per-page> directive, inside the tags of another directive:
<og-data-box heading="Tweet List" link="" uid="socialMentionsMeta" description="">
<div class="dataStatus">
{{dataStatus}}
<og-loading-indicator></og-loading-indicator>
</div>
<og-items-per-page></og-items-per-page>
<div class="dataContent" ng-show="dataContent" ng-mouseover="showGraphTrainingInfo()">
<og-social-media-mentions-list></og-social-media-mentions-list>
<div ng-show="showMorePostLoading" id="morePostLoadingContainer"><div id="morePostLoadingInner"></div></div>
</div>
</og-data-box>
The data-box directive:
(function () {
'use strict';
angular.module('portalDashboardApp')
.directive('ogDataBox', function () {
return {
restrict: 'E',
transclude: true,
replace: true,
scope: {
heading: '#',
link: '#',
uid: '#',
description: '#',
chartConfig: '#'
},
link: function (scope) {
scope.boxOpenCloseTitle = 'Collapse';
scope.iconStatus = 'upIcon';
scope.contentStatus = '';
var openCloseStatus = true;
var maximumSize = false;
scope.dataBoxUnderlayClass = '';
scope.dataBoxMaxMinClass = '';
scope.maxMinIcon = 'maximise';
scope.openCloseDataBox = function () {
if (openCloseStatus) {
scope.boxOpenCloseTitle = 'Expand';
openCloseStatus = false;
scope.iconStatus = 'downIcon';
scope.contentStatus = 'hideContent';
}
else {
scope.boxOpenCloseTitle = 'Collapse';
openCloseStatus = true;
scope.iconStatus = 'upIcon';
scope.contentStatus = '';
}
};
scope.maxMinDatabox = function () {
maximumSize = !maximumSize;
if (maximumSize) {
scope.dataBoxUnderlayClass = 'dataBoxUnderlayFullScreen';
scope.dataBoxMaxMinClass = 'dataBoxMaximised';
scope.maxMinIcon = 'minimise';
}
else {
scope.dataBoxUnderlayClass = '';
scope.dataBoxMaxMinClass = '';
scope.maxMinIcon = 'maximise';
}
};
},
templateUrl: './tpls/DataBoxTemplate.html'
};
});
})();
The data-box template:
<div ng-class="dataBoxUnderlayClass">
<section class="dataBox" id="{{uid}}" ng-class="dataBoxMaxMinClass">
<header class="dataBoxHeader">
{{heading}}
<img src="images/openCloseIcon.svg" title="{{boxOpenCloseTitle}}" width="15" height="15" class="openCloseBox {{iconStatus}}" ng-click="openCloseDataBox()" />
<img ng-mouseover="infoIconStyle='dataBoxInfoContentShow'" ng-mouseleave="infoIconStyle='dataBoxInfoContentHide'" src="images/info-icon.svg" height="15" class="dataBoxInfo" />
</header>
<div class="dataBoxContent {{contentStatus}}">
<div ng-class="infoIconStyle" class="dataBoxInfoContent">{{description}}</div>
<div ng-transclude></div>
</div>
</section>
</div>
What do I need to change so that I can nest my directive within other directives if I want to?
Thank you!
The problem comes from the isolated scope created by your directive.
The html inside og-data-box is under the directive scope and can't access to the controller scope.
As it is describe in this article http://angular-tips.com/blog/2014/03/transclusion-and-scopes/ if you want to access your controller scope inside <og-data-box></og-data-box> you need to append it to your isolated scope.
Something like that should correct your problem
app.directive('og-data-box', function() {
return {
restrict: 'EA',
scope: {
heading: '=',
link: '=',
uid: '=',
description: '='
},
transclude:true,
link: function(scope, element, attrs, ctrl, transclude) {
transclude(scope.$parent, function(clone, scope) {
element.append(clone);
});
}
};
});
EDIT :
As it is mentioned in the comment this is not the best way to do it.
You should pass your scope to the scope of og-data-box then you can use it in the nested directive :
og-data-box (I add selectedItemsPerPage to the scope)
(function () {
'use strict';
angular.module('portalDashboardApp')
.directive('ogDataBox', function () {
return {
restrict: 'E',
transclude: true,
replace: true,
scope: {
heading: '#',
link: '#',
uid: '#',
description: '#',
chartConfig: '#',
selectedItemsPerPage: '#'
},
link: function (scope) {
scope.boxOpenCloseTitle = 'Collapse';
scope.iconStatus = 'upIcon';
scope.contentStatus = '';
var openCloseStatus = true;
var maximumSize = false;
scope.dataBoxUnderlayClass = '';
scope.dataBoxMaxMinClass = '';
scope.maxMinIcon = 'maximise';
scope.openCloseDataBox = function () {
if (openCloseStatus) {
scope.boxOpenCloseTitle = 'Expand';
openCloseStatus = false;
scope.iconStatus = 'downIcon';
scope.contentStatus = 'hideContent';
}
else {
scope.boxOpenCloseTitle = 'Collapse';
openCloseStatus = true;
scope.iconStatus = 'upIcon';
scope.contentStatus = '';
}
};
scope.maxMinDatabox = function () {
maximumSize = !maximumSize;
if (maximumSize) {
scope.dataBoxUnderlayClass = 'dataBoxUnderlayFullScreen';
scope.dataBoxMaxMinClass = 'dataBoxMaximised';
scope.maxMinIcon = 'minimise';
}
else {
scope.dataBoxUnderlayClass = '';
scope.dataBoxMaxMinClass = '';
scope.maxMinIcon = 'maximise';
}
};
},
templateUrl: './tpls/DataBoxTemplate.html'
};
});
})();
And then when you call all the directive :
<og-data-box heading="Tweet List" link="" uid="socialMentionsMeta" description="" selected-items-per-page="selectedItemsPerPage">
<div class="dataStatus">
{{dataStatus}}
<og-loading-indicator></og-loading-indicator>
</div>
<og-items-per-page selected-items-per-page="selectedItemsPerPage"></og-items-per-page>
<div class="dataContent" ng-show="dataContent" ng-mouseover="showGraphTrainingInfo()">
<og-social-media-mentions-list></og-social-media-mentions-list>
<div ng-show="showMorePostLoading" id="morePostLoadingContainer"><div id="morePostLoadingInner"></div></div>
</div>
</og-data-box>
I neeed to pass a value from this part of the code in my directive to a controller, but not sure how to achieve that:
if (!scope.multiple) {
scope.model = value;
console.log(scope.model);
return;
}
I get the value in the console.log, I just don't know how to pass it to the controller.
This is the complete directive:
angular.module('quiz.directives')
.directive('fancySelect', function($rootScope, $timeout) {
return {
restrict: 'E',
templateUrl: 'templates/directives/fancySelect.html',
scope: {
title: '#',
model: '=',
options: '=',
multiple: '=',
enable: '=',
onChange: '&',
class: '#'
},
link: function(scope) {
scope.showOptions = false;
scope.displayValues = [];
scope.$watch('enable', function(enable) {
if (!enable && scope.showOptions) {
scope.toggleShowOptions(false);
}
});
scope.toggleShowOptions = function(show) {
if (!scope.enable) {
return;
}
if (show === undefined) {
show = !scope.showOptions;
}
if (show) {
$rootScope.$broadcast('fancySelect:hideAll');
}
$timeout(function() {
scope.showOptions = show;
});
};
scope.toggleValue = function(value) {
if (!value) {
return;
}
if (!scope.multiple) {
scope.model = value;
console.log(scope.model);
return;
}
var index = scope.model.indexOf(value);
if (index >= 0) {
scope.model.splice(index, 1);
}
else {
scope.model.push(value);
}
if (scope.onChange) {
scope.onChange();
}
};
scope.getDisplayValues = function() {
if (!scope.options || !scope.model) {
return [];
}
if (!scope.multiple && scope.model) {
return scope.options.filter(function(opt) {
return opt.id == scope.model;
});
}
return scope.options.filter(function(opt) {
return scope.model.indexOf(opt.id) >= 0;
});
};
$rootScope.$on('fancySelect:hideAll', function() {
scope.showOptions = false;
});
}
};
});
Updated
I tried to do as suggested in the answers by #Zidane and defining my object first in the controller like this:
$scope.year = {};
var saveUser = function(user) {
$scope.profilePromise = UserService.save(user);
console.log($scope.year);
This is the template:
<fancy-select
title="Klassetrinn"
model="year"
options="years"
enable="true"
on-change="onChangeYears()"
active="yearsActive"
name="playerYear"
form-name="registerForm"
>
</fancy-select>
But I got an empty object in that case.
When I define my objects like this I get the right value in the controller but in the view the title is not being displayed anymore:
$scope.search = {
years: []
};
var saveUser = function(user) {
$scope.profilePromise = UserService.save(user);
console.log($scope.search.years);
<fancy-select
title="Klassetrinn"
model="search.years"
options="years"
enable="true"
on-change="onChangeYears()"
active="yearsActive"
name="playerYear"
form-name="registerForm"
>
</fancy-select>
As you defined an isolated scope for your directive like this
scope: {
...
model: '=',
...
},
you give your directive a reference to an object on your controller scope.
Declaring the directive like <fancy-select model="myModel" ....></fancy-select> you pass your directive a reference to scope.myModel on your controller. When you modify a property on the scope.model object in your directive you automatically modify the same property on the scope.myModel object in your controller.
So you have to do
myApp.controller('myController', function($scope) {
...
$scope.myModel = {};
...
}
in your controller and in your directive just do
if (!scope.multiple) {
scope.model.value = value;
return;
}
Then you can get the value in your controller via $scope.myModel.value.
For clarification: You have to define an object on your controller and pass the directive the reference for this object so that the directive can follow the reference and doesn't mask it. If you did in your directive scope.model = 33 then you would just mask the reference passed to it from the controller, which means scope.model wouldn't point to the object on the controller anymore. When you do scope.model.value = 33 then you actually follow the object reference and modify the object on the controller scope.
you can use services or factories to share data between your angular application parts, for example
angular.module('myapp').factory('myDataSharing', myDataSharing);
function myDataSharing() {
var sharedData = {
fieldOne: ''
};
return {
setData: setData,
getData: getData,
};
function setData(dataFieldValue) {
sharedData.fieldOne = dataFieldValue;
};
function getData() {
sharedData.fieldOne
};
directive:
myDataSharing.setData(dataValue);
controller:
angular.module('myapp').controller('myController' ['myDataSharing'], function(myDataSharing) {
var myDataFromSharedService = myDataSharing.getData();
}
I need to pass a selected value from a directive that I am using in several places. It is a select input field that I need to get a selected value from.
This is how the directive looks like:
angular.module('quiz.directives')
.directive('fancySelect', function($rootScope, $timeout) {
return {
restrict: 'E',
templateUrl: 'templates/directives/fancySelect.html',
scope: {
title: '#',
model: '=',
options: '=',
multiple: '=',
enable: '=',
onChange: '&',
class: '#'
},
link: function(scope) {
scope.showOptions = false;
scope.displayValues = [];
scope.$watch('enable', function(enable) {
if (!enable && scope.showOptions) {
scope.toggleShowOptions(false);
}
});
scope.toggleShowOptions = function(show) {
if (!scope.enable) {
return;
}
if (show === undefined) {
show = !scope.showOptions;
}
if (show) {
$rootScope.$broadcast('fancySelect:hideAll');
}
$timeout(function() {
scope.showOptions = show;
});
};
scope.toggleValue = function(value) {
if (!value) {
return;
}
if (!scope.multiple) {
scope.model = value;
console.log(scope.model);
return;
}
var index = scope.model.indexOf(value);
if (index >= 0) {
scope.model.splice(index, 1);
}
else {
scope.model.push(value);
}
if (scope.onChange) {
scope.onChange();
}
};
scope.getDisplayValues = function() {
if (!scope.options || !scope.model) {
return [];
}
if (!scope.multiple && scope.model) {
return scope.options.filter(function(opt) {
return opt.id == scope.model;
});
}
return scope.options.filter(function(opt) {
return scope.model.indexOf(opt.id) >= 0;
});
};
$rootScope.$on('fancySelect:hideAll', function() {
scope.showOptions = false;
});
}
};
});
When I do console.log(scope.model); I get the selected value, but I am not sure how to get it and use it in my controller?
This is the controller:
angular.module('quiz.controllers')
.controller('ProfileController', function(
$scope,
$state,
$stateParams,
UserService,
$auth,
MessageService,
$ionicLoading,
AppSettings,
$timeout,
AvatarService,
PushService,
$http
) {
$scope.user = UserService.get();
$scope.profilePromise = {};
if ($scope.user.player.avatar == ""){
$scope.user.player.avatar = AvatarService.getRandom();
}
$http.get(AppSettings.apiUrl + '/years')
.then(function(result) {
$scope.years = result.data;
});
$scope.updateUser = function(form) {
if (!form.$valid) {
var message = "Ugyldig data i skjema. Sjekk felter markert med rødt.";
MessageService.alertMessage(message);
return;
}
saveUser($scope.user);
};
$scope.getNextAvatar = function() {
$scope.user.player.avatar = AvatarService.getNext($scope.user.player.avatar);
};
$scope.getPreviousAvatar = function() {
$scope.user.player.avatar = AvatarService.getPrevious($scope.user.player.avatar);
};
var saveUser = function(user) {
$scope.profilePromise = UserService.save(user);
$scope.profilePromise.then(function(result) {
$scope.user = result.data.user;
PushService.init();
PushService.getDeviceId().then(function(id) {
UserService.addDevice(id);
});
if ($stateParams.register) {
$state.go('main.front');
}
}, function(error) {
var message = "Kunne ikke lagre bruker. Melding fra server: " + error.data.message;
MessageService.alertMessage(message);
});
};
});
You already have an onChange binding in the scope, so why don't you use that one?
In your directive:
if (scope.onChange) {
scope.onChange({ $value: scope.model });
}
Then pass a controller function to your directive:
<fancy-select on-change="onChange($value)"></fancy-select>
In your controller:
$scope.onChange = function(val) {
// do something with the value
}
Hi I have one that throws owl carousel directive , but I have a factory that makes a call to the server getting the data I need to draw the container carousel owl , how do I get after the call $http is finished I draw the carousel owl ? My code is as follows
Directive
app.directive('wrapOwlcarousel',['$timeout',function ($timeout) {
return {
restrict: 'E',
link: function (scope, element, attrs) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
var options = scope.$eval($(element).attr('data-options'));
$(element).owlCarousel(options);
alert('carouel')
});
}
};
]});
Controller
app.controller('HomeController',[
'$scope','$location','$timeout','Storage',function($scope,$location,$timeout,Storage){
$timeout(function(){
angular.element('#footer').css({
'bottom' : '0'
})
},100);
$scope.getClass = function(path)
{
if ($location.path().substr(0, path.length) == path){
if (path == "/" && $location.path() == "/") { return "active"; }
else if (path == "/") { return ""; }
return "active"
} else { return "" }
}
var items = Storage.has('posts');
if(items){
$scope.eventos = Storage.get('posts');
}else{
alert('no info')
}
}
]);
Factory
app.factory('EventFunctions',['$http','appSettings',function($http,appSettings){
return {
getAllPosts : function(){
return $http.get(appSettings._url).then(function(result) {
return result.data;
});
}
}
}]);
Thanks to all!
i have found the answer!
my directive have an syntax error, this is my new directive file
app.directive('wrapOwlcarousel',['$timeout',function ($timeout) {
return {
restrict: 'E',
link: function (scope, element, attrs) {
$timeout(function () {
var options = scope.$eval($(element).attr('data-options'));
$(element).owlCarousel(options);
});
}
};
}]);
I have a problem: I use Angular and I need to use pushMsg method but I don't know how can I call it, boxCtrl.pushMsg(msg) does not work.
app.directive("fileread", function (socket) {
return {
scope: {
fileread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var msg = { author: 'me', class: 'me' };
// WHAT HERE???????
});
}
}
});
boxCtrl = function (socket, $scope) {
this.messages = [];
}
boxCtrl.prototype = {
pushMsg: function (message) {
this.messages.push(message);
}
}
app.controller('boxCtrl', boxCtrl);
You create an isolated scope and pass it as an attribute:
app.directive("fileread", function (socket) {
return {
scope: {
fileread: "=",
pushMessage: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var msg = { author: 'me', class: 'me' };
scope.pushMessage(msg);
});
}
}
});
And in your HTML:
<div fileread="..." push-message="pushMsg">
Edit: your controller should be something like this:
app.controller('Ctrl', function($scope) {
$scope.messages = [];
$scope.name = function(msg) {
$scope.messages.push(msg);
$scope.$apply(); //I think you need this to update the UI (not sure though)
}
})