AngularJS How access at content of {{ x.id }} from js - javascript

i'm a newbie with angularJS and actually i am working on Activiti.
I need to access an url with a specific ID (example taskId=12333) that change when a form is submitted.
How i can dynamically change the url so the taskId correspond to the new id? .
Here i get all task id (json format):
function githubController3($scope, $http, Base64) {
$http.defaults.headers.common['Authorization'] = 'Basic ' + Base64.encode('kermit' + ':' + 'kermit');
$http.get("http://localhost:8080/activiti-rest/service/runtime/tasks")
.then(function (response, data, status, headers, config) {
$scope.names = response.data.data;
});};
And the answer:
json Answer
I need to take ID from this answer and so form new URL.
function githubControllerForm1($scope, $http, Base64) {
$http.defaults.headers.common['Authorization'] = 'Basic ' + Base64.encode('kermit' + ':' + 'kermit');
$http.get("http://localhost:8080/activiti-rest/service/form/form-data?taskId=" + "**//here i need new ID dynamically**")
.then(function (response, data, status, headers, config) {
$scope.names = response.data.formProperties;
});};
Actually i get id with this in html:
<div ng-controller="githubController3">
<div ng-repeat="y in names">
{{ y.id }}
It's possible to assign the value of {{y.id}} to a $http.get request?
Thanks everyone that could help. Sorry if i was a bit unclear :)

Related

How to change hidden _token value of an html form data with ajax?

The main problem which I want to fix is the session expiration problem.
I use ajax to send login formData to server.
I use Laravel 5.4.
The form has an hidden element with _token value.
I have two ajaxes. The first one sends request to server which must bring back a new csrf token and the second one sends serialized login formdata.
I checked. The server successfully sends the needed new token value.
But the recommendations from google which I found change the element's csrf-token value.
But the ajax don't want to send that value, he is sending only _token value, not csrf-token.
I used the
headers: {
'X-CSRF-TOKEN': "{{csrf_token()}}",
},
still no effect.
I also tried this one
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
No result.
Interesting fact. When I reload the page with mouse click on browsers reload button the both csrf tokens are being updated, but when I write location.reload in ajax only csrf-token value is being changed. The _token value still the old value.
I even tried to make nested ajaxes, so after the location.reload it tries to send a request to server with the new token. But... anyway. It still send the same old token.
I have a not professional, low quality variant of solution: Change the needed value using the serialized string. I mean, cut the needed part of that string and put the part with the new value.
But I leave it as a last solution if nothing else I can find in future.
So what types of solutions you know or just some hints that may be helpful?
I found the problem and fixed it. The one thing I forgot to do was to use
$('input[name="_token"]').attr('value', result.token);
instead of
$('meta[name="csrf-token"]').attr('content', result.token);
here's the full ajax code
$.ajax({
url: "/"+lang+"/refreshToken",
type: 'get',
dataType: 'json',
success: function (result) {
console.log('New csrf token === ' + result.token)
$('input[name="_token"]').attr('value', result.token);
var loginForm = $("#login-form");
var formData = loginForm.serialize();
$.ajax({
url: '/' + lang + '/signin',
type: 'POST',
data: formData,
success: function (data) {
console.log(formData);
if (payment_login) {
var total = parseInt($('#your_total').html());
if (data < total) {
var mess = '<div class="alert alert-danger alert-dismissable fade in balanceIssue"> ' +
'<a href="#" class="close" data-dismiss="alert" aria-label="close">' +
'<i class="glyphicon glyphicon-remove"></i></a>' + $('#lang-notenoughmoney').val() + ' </div>';
$('.alert_messige').html(mess);
$('.submitPay').attr('data-original-title', $('#lang-notenoughmoney').val());
if (!$('.submitPay').hasClass('disabled')) {
$('.submitPay').addClass('disabled');
}
$('#sell-modal').show();
$('#signin-modal').hide();
} else {
sendPayment();
}
return false;
}
if (interchange) {
window.location.href = '/' + lang + '/interchange';
return false;
}
if (addAdvert) {
window.location.href = '/' + lang + '/add-adverts';
} else {
//location.reload();
location.href = '/' + lang + '/privacy';
}
},
error: function (data, err) {
$('.loginLoading').remove();
try {
var obj = jQuery.parseJSON(data.responseText);
if (obj.email) {
$('#login-email').addClass('has-error');
$('#login-errors-email').html(obj.email);
}
if (obj.password) {
$('#login-password').addClass('has-error');
$('#login-errors-password').html(obj.password);
}
if (obj.verify) {
$('#login-email').addClass('has-error');
$('#login-errors-email').html(obj.verify);
}
} catch (Exception) {
console.log('Sorry, but the responseText cannot be parsed into js object. The server sent you an html code with status code ' + data.status);
//location.href = '/'+lang+'/signin';
//location.reload();
}
}
})
},
error: function (xhr, status, error) {
console.log(xhr);
}
});

Including AngularJS code in HTML generated in JS

I'm working with an old version of AngularJS (1.3). I've got a page that I want to conditionally show different things based on the value in the database. If the value in the database is changed via user interaction, I want to update what's shown automatically. Part of what I show, however, is HTML and in that HTML I need to include some AngularJS code.
If the value is True, I want to show this HTML:
Your value is True. To set it to False, <a ng-click="myToggleFunction('paramValueFalse')">click here</a>.
If the value is False, I want to show this HTML:
You haven't done the thing, to do the thing, <a ng-click="myDifferentFunction('someOtherParamValue')">click here</a>.
I've got it so close to working: the content that shows changes out depending on what the user's value is, and it updates appropriately, and it's even rendering the HTML correctly (using $sce)... But the ng-click isn't functioning. Can you include angular in HTML that's being injected via JS like that?
Full code:
HTML:
<span ng-bind-html="renderHtml(html_content)"></span>
Controller:
function MyCtrl ($scope, $http, $sce, Notification) {
$scope.username = context.targetUsername;
$scope.content_options = {
'yes' : 'Your value is True. To set it to False, <a ng-click="myToggleFunction(" + "'paramValueFalse'" + ')">click here</a>.',
'no' : 'You haven\'t done the thing, to do the thing, <a ng-click="myDifferentFunction(" + "'someOtherParamValue'" + ')">click here</a>.'
}
$http.get(
'/api/v1/user/' + $scope.username + '/?fields=myBooleanField' // django rest api call
).then(function(response) {
$scope.user = response.data;
if ($scope.user.myBooleanField) {
$scope.html_content = $scope.content_options['yes'];
} else {
$scope.html_content = $scope.content_options['no'];
}
});
});
$scope.myToggleFunction = function(paramValue) {
// toggle value in the db
if (accepted === 'true') {
var success = "You turned on the thing";
var content = "yes";
} else {
var success = "You turned off the thing";
var content = "no";
}
$http({
method: 'GET',
url: '/api/v1/user/' + $scope.username + '/my_boolean_field/?value=' + paramValue, // django rest api call
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function(response) {
$scope.html_content = $scope.content_options[content];
Notification.success(success);
}, function(response) {
Notification.error("There was an error.");
});
};
$scope.myDifferentFunction = function(someOtherParamValue) {
// do some other stuff
};
$scope.renderHtml = function(html_code) {
return $sce.trustAsHtml(html_code);
};
}
MyCtrl.$inject = ['$scope', '$http', '$sce', 'Notification'];
As Sagar said above, the reason this is happening is because the html code returned by renderHtml is not compiled by AngularJS. I tried a few different takes on creating a directive that recompiles angular. For example:
https://github.com/incuna/angular-bind-html-compile
Rendering directives within $sce.trustAsHtml
ng-click doesn't fire when added post load
However, none of these were working for me. I'm not sure why; the content just wasn't displaying but there were no JS errors.
I ended up finding this solution, and it worked for me: Angular: ng-bind-html filters out ng-click?
Essentially, the solution is use raw JS to directly call the Angular functions, rather than using the ng-click directive in the JS-generated HTML content.
Here's what it looks like:
Template:
<div id="angularHtml" ng-bind-html="html_content">
<script>
function callAngular(controllerFunction, functionParam) {
var scope = angular.element(document.getElementById('angularHtml')).scope();
scope.$apply(function() {
{# couldn't figure out how to reference the function from the variable value, so this is hacky #}
if (controllerFunction == "myToggleFunction") {
scope.myToggleFunction(functionParam);
} else if (controllerFunction == 'myDifferentFunction') {
scope.myDifferentFunction(functionParam);
}
});
}
</script>
Controller:
function MyCtrl ($scope, $http, $sce, Notification) {
$scope.username = context.targetUsername;
$scope.content_options = {
'yes' : 'Your value is True. To set it to False, <a onClick="callAngular(\'myToggleFunction\', \'false\')">click here</a>.',
'no' : 'You haven\'t done the thing, to do the thing, <a onClick="callAngular(\'myDifferentFunction\', \'someValue\')">click here</a>.'
}
$http.get(
'/api/v1/user/' + $scope.username + '/?fields=myBooleanField' // django rest api call
).then(function(response) {
$scope.user = response.data;
if ($scope.user.myBooleanField) {
$scope.html_content = $sce.trustAsHtml($scope.content_options['yes']);
} else {
$scope.html_content = $sce.trustAsHtml($scope.content_options['no']);
}
});
});
$scope.myToggleFunction = function(paramValue) {
// toggle value in the db
if (accepted === 'true') {
var success = "You turned on the thing";
var content = "yes";
} else {
var success = "You turned off the thing";
var content = "no";
}
$http({
method: 'GET',
url: '/api/v1/user/' + $scope.username + '/my_boolean_field/?value=' + paramValue, // django rest api call
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function(response) {
$scope.html_content = $sce.trustAsHtml($scope.content_options[content]);
Notification.success(success);
}, function(response) {
Notification.error("There was an error.");
});
};
$scope.myDifferentFunction = function(someOtherParamValue) {
// do some other stuff
};
}
MyCtrl.$inject = ['$scope', '$http', '$sce', 'Notification'];
You can use ngShow and ng-hide for show and hide HTML dynamic
<div ng-show="DBvalue">Your value is True. To set it to False, <a ng-click="myToggleFunction('paramValueFalse')">click here</a>.</div>
<div ng-hide="DBvalue">You haven't done the thing, to do the thing, <a ng-click="myDifferentFunction('someOtherParamValue')">click here</a>.</div>

prevent multiple upvote Angularjs

To begin sorry for my English.
I made some search about this problem, but nothing works for me.
My problem is simple :
I have an upvote system, where users can upvote (like Stackoverflow). But the problem is that users can upvote multiple times (and it's not very well ..).
I tried to make a button with ng-disabled, but if i do this, users can only vote one time for all the posts (I mean if they upvoted "Post A", they can't upvote "Post B").
Here is my controller function :
$scope.incrementUpvotes = function(post) {
posts.upvote(post);
};
Here is my factory function :
o.upvote = function(post){
return $http.put('/posts/' + post._id + '/upvote', null, {
headers: {Authorization: 'Bearer '+auth.getToken()}
}).success(function(data){
post.upvotes += 1;
});
};
And here the html :
<span class="glyphicon glyphicon-thumbs-up" ng-click="incrementUpvotes(post)"></span>
If someone could help me it would be great ! Thanks in advance !
Please try to use button or input instead of span. Because disabled does not work in a span.
<button id="{{ post._id + 'upvote' }}" class="glyphicon glyphicon-thumbs-up" ng-click="incrementUpvotes(post)"></button>
Then set disabled attribute of your upvote button true after the upvote action.
o.upvote = function(post){
return $http.put('/posts/' + post._id + '/upvote', null, {
headers: {Authorization: 'Bearer '+auth.getToken()}
}).success(function(data){
post.upvotes += 1;
angular.element(document.getElementById(post._id + 'upvote' ))[0].disabled = true;
});
};
This is more of an architectural question than it is javascript/angularjs question. There are many ways to do this. But the idea is to store in database and persist upvote information, otherwise users can just refresh the page and upvote again.
Most direct solution is: You have to store your vote information on the backend at the user level. When you query the user information, store a list of up-voted posts like this:
myDataService should look like this:
angular.module("app", []).service("myDataService", ["$http","$q","$rootScope", function myDataService($http, $q, $rootScope) {
var myDataService = this;
myDataService.getPostsUpvoted = function(userId) {
var defer = $q.defer();
//here you format your payload to deliver userId to the api backend
var payload = { userId: userId };
//your api backend 'getpostsupvoted' should accept a userId, then in return it should
//deliver a list of posts upvoted by that user
$http.post("/api/getpostsupvoted", payload).then(function (data, status, headers, config) {
//call success
defer.resolve(data);
}, function(data, status, headers, config) {
//an error occurred
defer.reject(data);
});
return defer.promise;
}
return myDataService;
})];
Then, this is how you'll use the service in your controller.
//inject scope and myDataservice into controller
angular.module("app", []).controller("MainCtrl", ["$scope", "myDataService", function($scope, myDataService) {
//create a new array to hold a list of upvotes
$scope.user.upVoted = [];
myDataService.getPostsUpvoted($scope.user.id).then(function(data) {
//set upvoted array to data
$scope.user.upVoted = data;
}, function(error) {
//blah an error occurred
});
})];
In your controller, provide a function to check if a post has already been upvoted.
$scope.IsUpvotedAlready = function(postId) {
if($scope.user.upVoted.indexOf(postId) > -1)
return true;
return false;
}
You'll also have to push the post._id to the upVoted array and keep it there.
$scope.incrementUpvotes = function(post) {
//check if it's already been upvoted, then do nothing
if($scope.user.upVotes.indexOf(post._id) > -1)
return;
posts.upvote(post);
$scope.user.upVoted.push(post._id);
};
Then, in your ng-repeat directive where you display the post, check if the list of upvotes contain the post._id.
<div ng-repeat="post in posts">
<div ng-if="IsUpvotedAlready(post._id)">
<!-- display something since already upvoted !-->
</div>
{{ post }}
</div>
In the template when you are iterating the posts, have a flag for each post which identifies if it has been upvoted or not.
In the upvote function mark that flag as true and use it in the ng-disabled directive like this :
ng-disabled={{post.isUpvoted}}

Binding data with angular. (Calling method into a view)

I want to bind some data with angular, I made an example and it works but I'm having problems to integrate my stuff into another app.
This is the controller of that app
angular.module('app', ['dcafe.navigation','ui.bootstrap'])
.controller('HeadlineReportController', function($scope, $http, $interpolate, $filter, datafactory, d3Factory, $timeout){
//code
$scope.SendData = function(){
$http.post('http://localhost:8080/xxx/xxx/', data, config)
.success(function (data, status, headers, config) {
$scope.PostDataResponse = data;
console.log("Success");
console.log("Status code: " + status);
})
.error(function (data, status, header, config) {
//$scope.ResponseDetails = "Data: " + data +
console.log("Error");
console.log("Status: " + status);
console.log("Headers: " + header);
});
};
$scope.SendData();
//MORE CODE
});
I was working with the SendData() function that was inside a controller, in my view I used ng-controller and then the ng-repeat, but things are different in the second app.
They call the controller at the begining of the view like this:
<span ng-controller="HeadlineReportController as vm">
so I tried to do the ng-repeat like in my workig app, like this:
<tr ng-repeat="data in PostDataResponse.result"> </tr>
But as you can see in the controller above the $scope.SendData = function() {}
is part of the HeadlineReportController so in this case I dont know how to do my ng-repeat, I was thinking in something like this:
ng-repeat="data in SendData()"
But It's not working.
If you are using controller as syntax change $scope to 'this'
var self = this;
self.SendData = function(){
$http.post('http://localhost:8080/xxx/xxx/', data, config)
.success(function (data, status, headers, config) {
self.PostDataResponse = data;
console.log("Success");
console.log("Status code: " + status);
})
.error(function (data, status, header, config) {
//$scope.ResponseDetails = "Data: " + data +
console.log("Error");
console.log("Status: " + status);
console.log("Headers: " + header);
});
};
self.SendData();
And use your view model as declared on controller as
<tr ng-repeat="data in vm.PostDataResponse.result"> </tr>
There are two ways of declare and use the controllers. From the ngController documentation
Two different declaration styles are included below:
one binds methods and properties directly onto the controller using
this: ng-controller="SettingsController1 as settings"
one injects
$scope into the controller: ng-controller="SettingsController2"
The second option is more common in the Angular community, and is
generally used in boilerplates and in this guide. However, there are
advantages to binding properties directly to the controller and
avoiding scope.
You will need to change the code in your controller to the following:
angular.module('app',['dcafe.navigation','ui.bootstrap']).controller('HeadlineReportController',
function($http,$interpolate,$filter,datafactory,d3Factory,$timeout){
//code
var vm = this;
$vm.SendData = function(){
$http.post('http://localhost:8080/xxx/xxx/', data, config)
.success(function (data, status, headers, config) {
$scope.PostDataResponse = data;
console.log("Success");
console.log("Status code: " + status);
})
.error(function (data, status, header, config) {
//$scope.ResponseDetails = "Data: " + data +
console.log("Error");
console.log("Status: " + status);
console.log("Headers: " + header);
});
};
vm.SendData();
});
And your ng-repeat will change to
ng-repeat="data in vm.SendData()"
They are using the Controller As syntax in the view when they say <span ng-controller="HeadlineReportController as vm">.
Controller As is something you should look in to; John Papa has a good explanation here.
From your view, you would then reference controller variables like vm.SendData(). Also, with Controller As, you will not have $scope variables in your controller.

How to add eventlisteners after simple get request json in angularjs?

Ok so I am experimenting with Angular but I have run into a problem and maybe it is because I haven't adopted the Angular way of thinking yet, but this is basically what I ran into.
I get some data with a JSON request and show this data in a list using ng-repeat. So far so good. No errors in the console, but it does not attach the eventlistener to the ng-repeat elements. The code is fine, because with non ng-repeat elements it works like a charm. Someone else ran into this problem and how did you solve it? Thanks in advance.
<div ng-controller="basictrl">
<h1>Lijst van producten</h1>
<ul ng-repeat="item in producten">
<li>{{item.naam}}</li>
<li>{{item.prijs}}</li>
</ul>
</div>
JS
angular.module("app", ['ngRoute'])
.controller("basictrl", function ($scope, $http, producteffecten) {
$scope.producten = null;
$http({
method: 'GET',
url: 'producten.json'
}).
success(function (data, status, headers, config) {
$scope.producten = data;
$scope.showdescription = producteffecten.showdescription;
}).error(function (data, status, headers, config) {});
})
.factory('producteffecten', function() {
var effecten = {};
effecten.showdescription = $('ul').hover(function (){
$(this).append("<p>Test</p>");
});
return effecten;
})
The simple answer is: you can use $('ul').on("hover",function(){}). But this is not the angular way of thinking. The first improvement you could make is this:
add ng-mouseover="muisOverEffectje()" to the ul in the html
add $scope.muisOverEffectje=function(){ your event code} to the angular page
The next step to avoid adding the code with jquery to make it even more angular could be something like this:
add a parameter which gives the selected item to your event : muisOverEffectje(item)
add ng-show="showDescription" to the the ul
put show-description to true in the event handler
The last step could be: Make a directive for you . Like a product component for example.
Setting a timeout works, but it is hacky I guess. I will try to rewrite in a more angular way.
.factory('producteffecten', function() {
var effecten = {};
//SETTING TIMEOUT WORKS SOMEHOW
effecten.showdescription = setTimeout(function() {
$('ul').hover(function (){
$(this).append("<p>Test</p>");
});
}, 10);
return effecten;
})
You could also write an directive. Which is the nicest way in angular to do this kind of stuff:
Html:
<div ng-controller="basictrl">
<h1>Lijst van producten</h1>
<ul ng-repeat="item in producten" hover-text="item.effect">
<li>{{item.naam}}</li>
<li>{{item.prijs}}</li>
</ul>
</div>
js:
.controller("basictrl", function ($scope, $http, producteffecten) {
$scope.producten = null;
$http({
method: 'GET',
url: 'producten.json'
}).
success(function (data, status, headers, config) {
$scope.producten = data;
$scope.showdescription = producteffecten.showdescription;
}).error(function (data, status, headers, config) {});
})
.directive("hoverText",function(){
return {link:function(scope,elem,attr){
var insertElem=$("<div class='hovertext'>"+scope.hoverText+"</div>")
elem .mouseenter(function() {
insertElem.appendTo(elem);
})
.mouseleave(function() {
insertElem.remove();
});
},
scope:{"hoverText":"="}
};
});

Categories