AngularJS show result of HTTP request inside directive in template - angularjs

I'm trying to make GET request the first time I load an AngularJS (1.6) directive and show its result in the directive's template.
What I am trying so far is the following:
JS:
app.directive("myDirective", ['$http', function($http) {
return {
restrict: 'AE',
attrs: {
foo : String,
onResponse : function(response){
this.foo = response.data;
}
},
templateUrl: 'templates/my-directive.html',
compile: function(scope, element, attrs) {
$http({
method: 'GET',
url: 'my/url'
}).then(
attrs.onResponse
);
}
}
}]);
the HTML template:
<div id="my-directive">
foo: <span>attrs.foo</span>
</div>
Is there a way to do this properly?
Thanks in advance!

Well, I managed to do what I wanted by adding a controller:
app.directive("myDirective", ['$http', function($http) {
return {
restrict: 'AE',
controller: "myDirectiveController",
templateUrl: 'templates/my-directive.html'
}
}]);
where
app.controller('myDirectiveController', function ($scope, $http) {
$scope.foo;
$scope.onResponse = function(response){
$scope.foo= response.data;
}
$http({
method: 'GET',
url: 'my/url'
}).then(
$scope.onResponse
);
});
and the template looks like this:
<div id="my-directive">
foo: <span>{{foo}}</span>
</div>
Probably this is not the proper way to do it but it works.. Any suggestions are welcome!

Related

AngularJs custom directive with $http

I'm sorry but I got some troubles with AngularJs.
I have to get an image from S3 bucket and I want to inject it inside directive but I'm lost to how make it.
Here is what I made but, obviously it does not work and I'm pretty sure I'm in the wrong way.
No java code here because I know I properly get the image from S3 bucket.
.directive('logoApp', function(){
return {
restrict: 'A',
template: "<div class='logo' style='background-image:
url(data:image/png;base64,<image I want to inject>);'></div>",
scope: {
logoApp: "="
}
}
})
.service('StartService', function($scope, $http) {
$scope.logo = {
getFileFromS3 : function () {
$http({
method: 'GET',
url: '/**/{[path:[^\\.]*}'
}).then(function(data) {
console.log(data);
$rootScope.err({
title: 'Internal erro',
code: '500',
message: 'dialog_confirm_download_error'
});
});
}
}
})
Thank you
EDITED
I tried something like this and replace .service by .factory
.factory('StartService', function($http, $rootScope) {
return {
getFileFromS3: function () {
return $http({
method: 'GET',
url: '/<something>'
}).then(function (data) {
console.log("data" + JSON.stringify(data.data));
$rootScope.err({
title: 'Erreur Interne',
code: '500',
message: 'dialog_confirm_download_error'
});
});
}
}
})
And I can see I get my image in "data.data" but unfortunately, this part doesn't display my logo and let '{}' empty
.directive('logoApp', ['StartService', function(startService){
return {
restrict: 'E',
replace: true,
template: "<p>{{ logo }}</p>",
controller: function($scope) {
},
link: function($scope) {
console.log('start service ' + JSON.stringify(startService.getFileFromS3()));
$scope.logo = startService.getFileFromS3();
}
}
I believe this may be what you're looking for. I have changed the restrict to 'E' so that it is an element level directive and also added replace=true which will replace your directive element with the template from the directive.
Using the directive in your html would be like so:
<logo-app></logo-app>
Hope this helps.
.directive('logoApp', function(){
return {
restrict: 'E',
replace: true,
template: "<div class='logo' style='background-image:
url(data:image/png;base64,{{vm.imageData}});'></div>",
controller: ['StartService', function(StartService) {
var vm = this;
vm.imageData;
StartService.getFileFromS3()
.then(result => vm.imageData = result)
.catch(error => console.error(error));
}],
controllerAs: 'vm'
}
})
Please check the plunkr example for a live example using the code above.

How can I use both $http and $timeout in AngularJS directive?

This is a part of my codes
Object_Angular.directive("ntgChangeScanInnerHtmlWorkshop", ["$timeout", function($timeout){ ...
But I need to also get access to $http since I want to load things from my API. How can I do this?
What I have is a display of _ids in a <p></p>. Let say I have <p>{{collections._id}}</p>. I want that <p></p> to display the name field (collections.String_Name) not the _id. So I think to take the inner HTML of the <p>{{collections._id}}</p> after the value loads and then GET the String_Name from the API via { _id: innerHTMLValueOfP } then in .success I do set back the inner value with result.String_Name. Hence I need to have $http and $timeout in my directive to achieve this.
Example of using $http in directive
app.directive('myTag', ['$http', function($http) {
return {
restrict: 'E',
transclude: true,
replace: true,
scope:{
src:"="
},
controller:function($scope){
console.info("enter directive controller");
$scope.gallery = [];
console.log($scope.src);
$http({method: 'GET', url:$scope.src}).then(function (result) {
console.log(result);
}, function (result) {
alert("Error: No data returned");
});
}
}
}]);
or
app.directive('example', function( $http){
return {
restrict:'E',
link: function($scope,$element,$timeout){
$http.post('/example', {
data
}).success(function(data){
}).error(function(data){});
}
});

Directive isn't properly updating controller variable

I'm fairly new to Angular, and I'm trying to update one of my controller's variables from a directive, but it won't seem to work. The variable is populated in the directive, and when I log it there it's fine. Then when I try to log the variable from the controller; it logs fine at first, then it's "undefined".
I have no idea why this is happening. Help :(
Directive
app.directive('reportFilter', function() {
return {
restrict: 'E',
scope: {},
controller: 'MainController',
templateUrl: 'js/directives/reportFilter.html',
link: function(scope, element, attrs) {
scope.updateTable = function(selectedOffer,startDate,endDate) {
var offer='offer:'+selectedOffer.offer_id;
$.ajax({
type: 'POST',
url: 'daily_summary.php',
data: {
'offer': selectedOffer.offer_id
},
dataType: 'json',
cache: false,
success: function(response) {
scope.myvariable=response;
scope.getData();
console.log(scope.myvariable);
scope.$apply();
}
});
}
}
}
});
Controller
app.controller('MainController', ['$scope', 'service', 'Offerservice','$attrs', function($scope, service,Offerservice) {
$scope.getData= function () {
console.log($scope.myvariable);
return $scope.myvariable;
};
}]);

Directive scope got undefined

I get an issue with passing data to angular directives inside ng-repeat, it always got undefined. Here are my code
The Controller:
angular.module('module').controller('ModuleController', ['$scope', 'MyService', function($scope, MyService) {
$scope.getData = function() {
$scope.data = MyService.myGetRequest(); // returning array of objects
};
});
View:
<div ng-controller="ModuleController" ng-init="getData()" ng-switch="data.length > 0">
<div ng-repeat="d in data" ng-switch-when="true">
<my-directive data="d.object"></my-directive>
</div>
</div>
Directive:
angular.module('module').directive('myDirective', [function() {
return {
restrict: 'E',
template: '<div></div>' // let's ignore the template for now,
scope: { data: '=' },
link: function(scope, el, attrs) {
console.log(scope.data); // always undefined
}
};
}]);
Service:
angular.module('module').factory('MyService', ['$resource', function($resource) {
return $resource('/data/:id',
{ id: '#_id' },
{
myGetRequest: { method: 'GET', isArray: true }
});
}]);
I thought it was because the $scope.data still empty when the template loaded. If yes, anyone know what is the solution? Thanks in advance. :)
EDIT: btw, if I put <my-directive data="data"></my-directive> instead of <my-directive data="d.object"></my-directive> the scope.data is not undefined anymore, it will show my array of object from resource.
EDIT2: this <my-directive data="d"></my-directive> will also resulting scope.data in my directive got undefined.
EDIT3: Add service code snippet
I think Shomz found the problem. You should use a promise with async call. Like this:
angular.module('module').controller('ModuleController', ['$scope', 'MyService',
function($scope, MyService) {
$scope.data = [];
MyService.myGetRequest().$promise.then(function(data) {
$scope.data = data;
});
}
});

Angular directive not capturing values in local scope

I have the following html.
<h2>{{ profile.first_name }} {{ profile.last_name }}</h2>
<p>{{ profile.organisation_name }}</p>
<p>{{ profile.email }}</p>
<p>{{ profile.phone }}</p>
<div class="row marketing">
<transform xml="{{ profile.profiles.profile }}" xslt="LawyerProfile.xslt"/>
</div>
I have an angular service that populates profile object. I have some xml data in {{ profile.profiles.profile }} that I want to transform using a directive.
So I pass in the data and xslt file to apply transform from.
my directive looks like this
'use strict';
clientApp.directive("transform", function () {
return {
restrict: "E",
scope: {
xml: "#",
xslt: "#"
},
replace: true,
transclude: false,
link: function (scope, element) {
console.log(scope);
console.log(scope.xml);
console.log(scope.xslt);
}
};
});
When I inspect the scope object, it have xml data as string in scope.xml but when I console.log it, its not there.
console.log(scope.xslt); works just fine.
Any help will be much appreciated, thanks.
UPDATED:
profileController.js
'use strict';
clientApp
.controller('profileController', function($scope, $routeParams, profileService) {
profileService.getProfile($routeParams.id, $routeParams.publication)
.then(function(profile) {
$scope.profile = profile;
});
});
profileService.js
'use strict';
clientApp.factory('profileService', function($http, $q) {
return {
getProfile: function(id, publication) {
var deferred = $q.defer();
var url = 'http://192.168.7.37:3000/lawyer/' + id + '/' + publication;
$http({ method: 'GET', url: url })
.success(function(data, status, headers, config) {
deferred.resolve(data);
})
.error(function(data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
};
});
The problem is that xml is bound to an interpolated value, which is from the $resource service, therefore it's a good idea to use $timeout to let angular's digest cycle finish before you do anything else.
You can try something like this:
.directive("transform", function ($timeout) {
return {
...
link: function (scope, element) {
...
$timeout(function() {
console.log(scope.xml);
}, 0);
}
};
});

Resources