Error in LInking service and directive in Angular - angularjs

I have an issue at linking service having http to a directive. This is the code of that...
myapp.factory ( 'autoCompleteDataService', ['$http', function($http) {
return {
getSource: function(callback) {
var url = 'get_data_from_server.php';
$http.get(url).success(function(data) {
callback(data);
});
}
}
} ] );
myapp.directive('autoComplete', function(autoCompleteDataService) {
return {
restrict: 'A',
link: function(scope, elem, attr, ctrl) {
elem.autocomplete({
source: autoCompleteDataService.getSource(),
select: function( event, ui ) {
scope.$apply(function() {
scope.item.unit_id = ui.item.value;
});
},
minLength: 2
});
}
};
});
I replaced callback(data); with return data; with no result...
Any help is appreciated..
Edit: added working code without http
If I keep this code instead the above one its working
myapp.factory('autoCompleteDataService', [function() {
return {
getSource: function() {
return ['apples', 'oranges', 'bananas'];
}
}
}]);

Another way to answer the issue,, with full filtering logic at server side..
myapp.directive('autoComplete', function(autoCompleteDataService) {
return {
restrict: 'A',
link: function(scope, elem, attr, ctrl) {
elem.autocomplete({
source: function( request, response ) {
$.ajax({
url: "./get_data_from_server.php",
dataType: "json",
data: {
maxRows: 10,
startsWith: request.term
},
success: function( data ) {
response(data);
}
});
},
select: function( event, ui ) {
scope.$apply(function() { scope.item.unit_id = ui.item.value; });
},
minLength: 2
});
}
};
});

myapp.factory('autoCompleteDataService', ['$http', function($http) {
return {
getSource: function() {
var url = 'get_data_from_server.php';
return $http.get(url);
}
}
}]);
Directive:
link : function(scope, elem, attr, ctrl) {
autoCompleteDataService.getSource().success(function(data) {
elem.autocomplete({
source: data,
select: function( event, ui ) {
scope.$apply(function() { scope.item.unit_id = ui.item.value; });
},
change: function (event, ui) {
if (ui.item === null) {
scope.$apply(function() { scope.foo = null });
}
},
minLength: 2
});
});
}

Related

AngularJS Directive data binding not happening from controller

I am facing the problem of data binding from controller to directive because of delay in response from the server.
To better understand just see a small program below.When I remove the timeout function, binding happens.
<msg track="{{customer}}"></msg>
angular.module('myApp').directive('msg', function() {
return {
scope: {
track :"#"
},
link : function(scope, element, attrs) {
},
template : "<a href>{{track}}</a>"
}
});
angular.module('myApp').controller('HomeCtrl', ['$scope', function($scope) {
setTimeout(function() {
$scope.customer = "shreyansh";
}, 5000);
// assume some service call inside controller
// service1.getData().then(function(data){$scope.customer = data})
}]);
How can i fix above problem so that above code should render as
<msg track="shreyansh" class="ng-isolate-scope">shreyansh</msg>.
Any help is appreciated.
Thanks
var app = angular.module('plunker', []);
app.factory('myService', function($http) {
var promise;
var myService = {
getData: function() {
if (!promise) {
promise = $http.get('test.json').then(function(response) {
return response.data;
});
}
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function(myService, $scope) {
myService.getData().then(function(d) {
$scope.data = d;
});
});
app.directive('msg', function() {
return {
restrict: 'E',
scope: {
track: "#"
},
link: function(scope, element, attrs) {
},
template: "<a href>{{track}}</a>"
}
});
<msg track="{{data.name}}"></msg>
test.json file
{
"name": "Pete"
}

angularjs nested cascading directive for dropdown

I want to create a cascading dropdown directive .
<my-dropdown label="states" url="http://statelisturl">
<my-dropdown label="cities" url="http://citylisturl">
</my-dropdown>
</my-dropdown>
But states will be list first, when I select a state cities will be get from url.
Is this possible for angularjs technically? Or I should be seperated directive for every dropdown?
You could do something like this:
.directive("myDropdown", function() {
return {
restrict: "E",
require: ["myDropdown", "?^^myDropdown"],
template: "<select ng-options='opt as opt.label for opt in $ctrl.options' ng-model='$ctrl.selectedOption' ng-change='$ctrl.changed($ctrl.selectedOption)'></select><div ng-transclude></div>",
scope: true,
bindToController: {
url: "#",
label: "#"
},
controller: function($scope, $http) {
var _self = this;
_self.init = function() {
$http.get(_self.url).then(function(response) {
_self.options = response.data;
});
}
_self.parentChanged = function(item) {
var id = item.id;
$http.get(_self.url + "?id=" + id).then(function(response) {
_self.options = response.data;
});
}
},
link: function(scope, element, attrs, ctrls) {
var ctrl = ctrls[0];
var parentCtrl = ctrls[1];
if (parentCtrl) {
scope.$watch(function() {
return parentCtrl.selectedOption;
}, function(newval) {
if (newval) {
ctrl.parentChanged(newval);
}
});
} else {
ctrl.init();
}
},
controllerAs: "$ctrl",
transclude: true
}
});
EDIT: I have a working example here

Cannot access DOM inside ngRepeat inside custom directive

In the following example (http://jsfiddle.net/akanieski/t4chbuwq/1/) I have a directive that has an ngRepeat inside it... during the link stage I cannot access html inside the ngRepeat. Only thing inside shade-element is <!-- ngRepeat i in items --> What am I doing wrong?
Controller:
module.controller("MainCtrl", function($scope, $timeout) {
$scope.currentPanel = 1;
$timeout(function(){
$scope.items = [1,2];
}, 1000)
$scope.loadPanelOne = function() {
if (!$scope.$$phase) $scope.$apply(function(){$scope.loadingPanelOne = true;});
$timeout(function(){
$scope.loadingPanelOne = false;
}, 2000);
}
$scope.loadPanelTwo = function() {
if (!$scope.$$phase) $scope.$apply(function(){$scope.loadingPanelTwo = true;});
$timeout(function(){
$scope.loadingPanelTwo = false;
}, 2000);
}
$scope.loadPanel3 = function() {
if (!$scope.$$phase) $scope.$apply(function(){$scope.loadingPanel3 = true;});
$timeout(function(){
$scope.loadingPanel3 = false;
}, 2000);
}
$scope.loadPanel4 = function() {
if (!$scope.$$phase) $scope.$apply(function(){$scope.loadingPanel4 = true;});
$timeout(function(){
$scope.loadingPanel4 = false;
}, 2000);
}
});
Directives:
var module = angular.module("myApp", []);
module.directive('shadeSet', ['$rootScope', '$timeout', function($rootScope, $timeout) {
return {
restrict: "E",
scope: {
"mode": "=",
"currentPanel": "="
},
controller: function() {
},
link: function(scope, element, attributes) {
$rootScope.$on('panelOpening', function(ev, args) {
if (scope.mode === 'exclusive') {
element
.find('shade-panel')
.addClass('hide')
$('[id="' + args.id + '"]',element).removeClass('hide');
} else if (args.state === 'open') {
$('[id="' + args.id + '"]',element).removeClass('hide');
} else if (args.state === 'close') {
$('[id="' + args.id + '"]',element).addClass('hide');
} else {
$('[id="' + args.id + '"]',element).toggleClass('hide');
}
$rootScope.$broadcast('panelOpened', {id: args.id, state: 'open'});
})
if (scope.currentPanel) {
$rootScope.$broadcast('panelOpening', {id: scope.currentPanel, state: 'open'});
}
}
}
}])
module.directive('shadePanel', ['$rootScope', function($rootScope) {
return {
restrict: "E",
require: '^shadeSet',
scope: {
"id": "=",
"onOpen": "&",
"scrollOnOpen": "="
},
link: function(scope, element, attributes) {
$rootScope.$on('panelOpened', function(ev, args){
if (args.id === scope.id && scope.onOpen) scope.onOpen();
if (scope.scrollOnOpen) {
console.log("Scrolling to " + args.id)
$('html, body').animate({
scrollTop: $(element).offset().top
}, 500);
}
})
}
}
}])
module.directive('shadeToggle', ['$rootScope', function($rootScope) {
return {
restrict: "E",
require: '^shadeSet',
scope: {
target: "="
},
compile: function() {
return {
pre: function(scope, element, attributes) {
element.on('click', function() {
$rootScope.$emit('panelOpening', {id: scope.target});
});
scope.$on('$destroy', function() {
element.off('click');
});
}
};
}
}
}])
HTML
<div ng-controller="MainCtrl" ng-app="myApp">
<shade-set current-panel="currentPanel">
<div ng-repeat="i in items">
<shade-toggle target="1"><a href>Open One</a></shade-toggle>
<shade-panel id="1" class="hide" on-open="loadPanelOne()">
<span ng-show="loadingPanelOne">... Loading Panel 1 ...</span>
Hello World
</shade-panel>
</div>
</shade-set>
</div>

Inject service into directive

Cant inject the comment service into comment directive getting errorComment service not found
// Code goes here
var noBlogApp = angular.module("noBlogApp", ['ngRoute', 'ngSanitize', 'commentSystem']);
noBlogApp.config(['routeProvider', function(routeProvider) {
routeProvider.null when('/', {
controller: "noBlogController", null templateUrl: 'post.html',
}).when('/post/:id', {
controller: 'singlePostController',
templateUrl: 'singlepost.html',
});
}]);
noBlogApp.service('commentService', ['http', function(http) {
http.get('js/assureBlog.JSON').success(function(data) {
this.getComment = function(id) {
scope.comment = data[id];
return scope.comment;
}
var addComment = function() {
}
var addReply = function() {
}
var deleteComment = function() {
}
var deleteReply = function() {
}
});
}]);
noBlogApp.controller('noBlogController', ['scope', 'http', function(scope, http) {
scope.message = "hello";
http.get('js/assureBlog.JSON').success(function(data) {
scope.post = data;
});
}]);
nullnoBlogApp.controller('singlePostController', ['scope', 'http', 'routeParams', 'commentService', function(scope, http, routeParams, commentService) {
null http.get('js/assureBlog.JSON').success(function(data) {
scope.post = data[routeParams.id];
});
scope.commentService = commentService;
console.log("this is the" + commentService) null
}]);
noBlogApp.directive('comments', ["commentService", function(commentService) {
return {
scope: {
id: '#'
},
template: id: {
{
id
}
}
link: function(scope, element, attrs, commentService) {
console.log(scope.commentService);
}
};
}]);
Although the question is poorly formatted, it looks like your issue is this:
link:function(scope,element,attrs,commentService)
Remove the commentService from the link function. You've already added the dependency to the directive construction.

Why is my $watch not getting called?

I just don't understand why my $watch is NOT called a second time with the updated value of "entity".
.directive('myParent', function() {
return {
controller: function($scope, $log) {
$scope.$on('thingChanged', function(e, newVal) {
$log.log('thingChanged event hit...');
$scope.$apply(function() {
$scope.thing = newVal;
});
});
},
template: '<div><div my-child entity="thing" v="{{thing.awesome}}"></div><div my-child2></div></div>'
};
})
.directive('myChild', function($parse, $log) {
return {
controller: function($scope) {
},
scope: {
entity: '=',
v: '#'
},
link: function(scope, element, attrs) {
$log.log('v in link:');
$log.log(scope.v);
attrs.$observe('v', function(v) {
$log.log('v in observe in link:');
$log.log(v);
})
$log.log('entity in link:');
$log.log(scope.entity);
scope.$watch(scope.entity, function(nv, ov) {
$log.log('$watch detected change: ');
$log.log(scope.entity);
});
},
template: '<span>{{v}}</span>-<span>{{entity}}</span>'
};
})
.directive('myChild2', function($parse, $log, $timeout) {
return {
controller: function($scope) {
var count = 0;
$timeout(function() {
$scope.$emit('thingChanged', { awesome: 'cool'+count++ });
}, 2000);
},
scope: true,
link: function(scope, element, attrs) {
},
template: '<span><button ng-click="change()"</span>'
};
})
Plunker: http://plnkr.co/edit/2jfa1dcwguO400zRjJxU?p=preview
Watch should be the name of the property to be watched, try scope.$watch("entity", ..., if you want to deep watch (that is object properties) call it with true as the last parameter.
scope.$watch("entity", function() { ... }, true);

Resources