How to run owl carousel after http call with angularjs - javascript

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);
});
}
};
}]);

Related

How can I call a Service from a Directive in AngularJS

I currently have a directive that is called whenever a click event happens. This helps me change the icon for adding to user's favorite list.
View:
<div class="col col-33">
<i class="icon ion-ios-heart-outline" favorite="place[0].objectId" on-icon="ion-ios-heart-outline" off-icon="ion-ios-heart" icon-switcher /></i>{{place[0].likes}}
</div>
Directive:
.directive('iconSwitcher', function() {
return {
restrict : 'A',
scope: {
favorite: '='
},
link : function(scope, elem, attrs, PlaceService, ) {
var currentState = true;
elem.on('click', function() {
console.log('objectId',scope.favorite);
if(currentState === true) {
angular.element(elem).removeClass(attrs.onIcon);
angular.element(elem).addClass(attrs.offIcon);
} else {
angular.element(elem).removeClass(attrs.offIcon);
angular.element(elem).addClass(attrs.onIcon);
}
currentState = !currentState
});
}
};});
I will like to call a service from this directive when the click event happens like i do from a controller. Here is a sample of the service i want to call
$scope.addFavorite = function(objectId){
PlaceService.addFavorite(objectId,currentUser)
Angular will not inject the service into the link function.Inject your service in the directive and use like in the controller.
.directive('iconSwitcher', ['PlaceService', function(PlaceService) {
// Use PlaceService here as a simple service
return {
restrict : 'A',
scope: {
favorite: '='
},
link : function(scope, elem, attrs) {
var currentState = true;
elem.on('click', function() {
console.log('objectId',scope.favorite);
if(currentState === true) {
angular.element(elem).removeClass(attrs.onIcon);
angular.element(elem).addClass(attrs.offIcon);
} else {
angular.element(elem).removeClass(attrs.offIcon);
angular.element(elem).addClass(attrs.onIcon);
}
currentState = !currentState;
})
};
]})
Angular don't inject dependencies in the link function, you have to take it in the function declaration of the directive itself :
angular.directive('myDirective', function(myService) {
return {
// ...
link: function(...) {
myService.addFavorite(objectId, currentUser);
}
}
});

How to get value from directive in Angular

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();
}

Directive to Hide/Show elements based on Session Service - AngularJS

Following up this answer, I was trying to build two directives to allow/deny elements to be visible by the end user.
angular.module('app.directives').directive('deny', ['SessionTool', function (SessionTool) {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
scope.$watch(SessionTool.user, function (value, oldValue) {
var list = attrs.deny.split(',');
if (SessionTool.hasAnyRole(list))
return elem.hide();
return elem.show();
});
}
}
}]);
My problem is that when I do make the logon, the $watch function is not being called again to make the invisible element appear.
A resume of my SessionTool is listed below.
angular.module('app.tools').factory('SessionTool', ['$cookies', function ($cookies) {
var _cookieKey = 'user';
return {
user: {},
init: function () {
var u = $cookies.get(_cookieKey);
try {
u = angular.fromJson(u);
this.user = u;
} catch (e) {
console.log('invalid json');
}
},
login: function (u) {
this.user = u;
$cookies.putObject(_cookieKey, u, {path: '/'}); // #TODO encrypt the whole JSON before saving it to cookies.
},
...
};
}]);
Anybody could point out why the $watch isn't being fired?
Thanks in advance.
I think that your directive is currently watching an anonymous variable SessionTool.user in your directive scope not the actual variable. I suggest going with this approach instead.
angular.module('app.tools').factory('SessionTool', ['$cookies','$rootScope', function ($cookies) {
var _cookieKey = 'user';
var _user = {};
return {
setUser: function(user) {
_user = user;
$rootScope.$broadcast('SessionToolChange');
}
getUser: function() {
return _user;
}
init: function () {
var u = $cookies.get(_cookieKey);
try {
u = angular.fromJson(u);
this.user = u;
} catch (e) {
console.log('invalid json');
}
},
login: function (u) {
this.user = u;
$cookies.putObject(_cookieKey, u, {path: '/'}); // #TODO encrypt the whole JSON before saving it to cookies.
},
...
};
}]);
angular.module('app.directives').directive('deny', ['SessionTool', function (SessionTool) {
return {
restrict: 'A',
controller: function (scope, elem, attrs) {
scope.$on('SessionToolChange', function (value, oldValue) {
// get the user and do your stuff.
});
}
}
}]);

AngularJS share data bettween parent and child scope directives

I have a widget like directive called waComments, it loads components via a RESTful service and displays them. In my view I'm using ng-repeat to loop over them and to render them with a button that if pressed Shows a new reply to form. This his handled by the waCommentsReply directive. One waComments widget has many child directives of type waCommentsReply. When the form is filled and submitted I want to add the new comment on top of my comments list. So both directives have to share the comments data.
I've tried to implement this here Sharing data between directives but without much success, the comment data is not updated when I add a new comment. I see that the RESTful API calls work and the data is returned, so this is not an issue.
Why is my implementation of Sharing data between directives not working in my case?
waCommentsReply directive:
waFrontend.directive('waCommentsReply', ['$rootScope', 'Comment', 'WaFormValidation', 'WaCommentStore', function($rootScope, Comment, WaFormValidation, WaCommentStore) {
return {
restrict: 'E',
templateUrl: '/stubs/comment-form.html',
transclude: true,
scope: {
replyTo: '#replyTo',
replyFormList: '=replyFormList',
loggedIn: '#loggedIn',
model: '#model',
id: '#id',
cancelButton: '#cancelButton'
},
controller: function($scope) {
$scope.comments = WaCommentStore;
if ($scope.cancelButton == undefined) {
$scope.cancelButton = true;
} else {
$scope.cancelButton = false;
}
$scope.comment = $scope.commentForm = {
Comment: {
author_name: '',
body: '',
model: $scope.model,
foreign_key: $scope.id,
parent_id: $scope.replyTo
}
};
$scope.$watch('replyFormList', function (newValue, oldValue) {
if (newValue) {
$scope.replyFormList = newValue;
}
});
if ($scope.loggedIn == undefined) {
$scope.loggedIn = false;
}
/**
* Handles the submission and response of a reply
*
* #return void
*/
$scope.reply = function() {
Comment.add($scope.comment).then(function(result) {
if (result.status == 'fail' || result.validation != undefined) {
$scope.validationErrors = result.validation;
WaFormValidation.validate(result.validation, $scope.commentForm);
} else if (result.status == 'success') {
//$scope.$parent.comments.unshift(result.data.comment);
//$scope.comments.unshift(result.data.comment);
$scope.comments.comments.unshift(result.data.comment);
//WaCommentStore.append($scope.model, $scope.id, result.data.comment);
$scope.comments, $scope.id, result.data.comment
$scope.comment = {};
$scope.replyFormList[$scope.replyTo] = false;
}
});
};
$scope.close = function() {
$scope.comment = {};
if ($scope.replyFormList[$scope.replyTo] != undefined) {
$scope.replyFormList[$scope.replyTo] = false;
}
}
}
};
}]);
WaCommentStore directive:
waFrontend.factory('WaCommentStore', function() {
return {
comments: []
};
});
waComments directive:
waFrontend.directive('waComments', ['$rootScope', 'Comment', 'WaCommentStore', function($rootScope, Comment, WaCommentStore) {
return {
restrict: 'E',
templateUrl: '/stubs/comments.html',
scope: {
model: '#commentModel',
id: '#commentFk'
},
controller: function($scope) {
$scope.comments = WaCommentStore;
$scope.loaded = false;
$scope.loadedMore = true;
$scope.currentPage = 1;
$scope.loggedIn = false;
$scope.paging = {};
$scope.replyFormList = {};
Comment.comments($scope.model, $scope.id).then(function(result) {
$scope.comments.comments.push.apply($scope.comments.comments, result.data.comments);
$scope.loggedIn = result.data.loggedIn;
$scope.paging = result.paging.Comment;
$scope.loaded = true;
});
$scope.loadMore = function() {
$scope.loadedMore = false;
if ($scope.paging.nextPage == false) {
//return false;
}
var options = {
page: $scope.paging.page + 1
};
Comment.comments($scope.model, $scope.id, options).then(function(result) {
$scope.comments.comments.push.apply($scope.comments.comments, result.data.comments);
$scope.paging = result.paging.Comment;
$scope.loadedMore = true;
});
};
$scope.submitComment = function() {
//alert($scope.author_name + $scope.body);
};
$scope.reply = function(replyId) {
$scope.replyFormList[replyId] = true;
}
}
};
}]);
since in both directive you defined scope: {} basically it means you defined those directives to use isolated scope.
with isolated scope, a scope/directive can't see what is in the parent scope.
however parent scope, can be affected by the child scope changes with 2 way binding definition.
https://docs.angularjs.org/guide/scope
try changing the shared data like this
waFrontend.factory('WaCommentStore', function() {
var comments = [];
var getComments = function() { return comments; }
var setComments = function(data) { comments = data; }
return {
getComments : getComments ,
setComments : setComments
};
});
I wanted to put it as a comments, but it would have been difficult to understand for you.
Please let me know if this works, else I will delete this answer.

why ng-click not working?

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');
}
});
}
};
});

Categories