Angular - populate list with AJAX - javascript

I am working on a web app, and I want to show data in a list, by category. I am getting back AJAX data that has a title, and a category. The code to get that is like this:
angular.module('getImageData', ['ngResource'])
.factory('images', function ($resource)
{
return $resource('/ImageData/GetImages', {}, {
query: { method: 'GET', isArray: true }
});
});
and then like this:
$scope.imageData = images.query(function (response)
{
// This has become superfluous
return response;
});
The AJAX call us occurring and I can see my data in Chrome.
Then here is my HTML:
<ul>
<li data-ng-repeat="image in imagedata">
{{image.Title}}
</li>
</ul>
I intend to do this:
<ul>
<li data-ng-repeat="image in imagedata | filter : {TypeFilter : 'a' }">
{{image.Title}}
</li>
</ul>
but for now I'm keeping it simple.
The list is never rendered. This is the HTML I see in chrome:
<ul>
<!-- ngRepeat: image in imagedata -->
</ul>
I am assuming this means it ran before the data came back. How do I make it wait ?
Thanks.

You have a spelling mistake in image in imagedata. It should be image in imageData
You also do not need to write callback function for query
$scope.imageData = images.query();

try changing this:
$scope.imageData = images.query(function (response)
{
// This has become superfluous
return response;
});
to this:
$scope.imageData = images.query(function (response)
{
$scope.imageData = response;
});

Related

Data update without page reload jinja2

The data has to be refreshed without page reload. Originally data is appeared on html with jinja2.
#app.route('/personal_account', methods=['POST'])
def welcome():
login = request.form['login']
data = get_default_user_data(login)
# ... processing
return render_sidebar_template("personal_account.html", data=data)
According to these data graph is building with chartist.js.
personal_account.html
<div id="data">
<ul id="consumed_values">
{% set count = 0 %}
{% for i in data.consumed_values %}
<li>{{ data.consumed_values[count] }}</li>
{% set count = count + 1 %}
{% endfor %}
</ul>
</div>
<canvas width="800" height="600" id="canvas"></canvas>
<button id="button">Update</button>
I need to update data. I am using ajax.
The function "request" make a post request to the server to the function get_selected_values in Python.
This function gives new data. But new data doesn't display in jinja2 on page. The data is still old.
personal_account.js
window.onload = draw();
function draw() {
var consumed_values = document.querySelectorAll('ul#consumed_values li');
var values = new Array();
for (var i = 0; i < consumed_values.length; i++) {
console.log(consumed_values[i].innerHTML);
values[i] = consumed_values[i].innerHTML;
}
var numbers = new Array();
for(var i=0; i<consumed_values.length; i++)
{
numbers[i]=i+1;
console.log(numbers[i]);
}
var ctx = document.getElementById('canvas').getContext('2d');
var grapf = {
labels : numbers,
datasets : [
{
strokeColor : "#6181B4",
data : values
}
]
}
new Chart(ctx).Line(grapf);
}
document.getElementById('button').onclick=function () {
request();
}
function reques() {
var first = selected[0];
var second = selected[1];
first.month = first.month+1;
second.month = second.month+1;
$.ajax({
type: 'POST',
url: '/get_selected_values',
success: function(response) {
alert('Ok');
draw();
},
error: function() {
alert('Error');
}
});
}
Function get_selected_values()
#app.route('/get_selected_values', methods=['POST'])
def get_selected_values():
# ...
data = fetch_selected_date(start_date=start_date, end_date=end_date, login=current_user.get_id())
if data:
# return jsonify({'result': True, 'data': data}) # does not work this way
# return jsonify({'result': False, 'data': []})
return render_sidebar_template("personal_account.html", data=data, result=1)
How to succeed in data's update and graph's rebuild?
EDIT 1
I am using the first version of get_selected_values function.
The request function look like this:
...
success: function(response) {
alert('Успешно получен ответ:!'+ response.data);
document.getElementById('consumed_values').innerHTML = response.data;
draw();
},
...
Data is updating successfully, but graph looks the same. How to fix?
OK here's my outlook on this. You're on the right track and there is a way to update the element without the need to re-draw the page in this instance. What's happening is that you are returning data from your get_selected_values() method but not doing anything with it once it's returned to your AJAX request.
So firstly, I'm going to draw your attention to your AJAX request:
$.ajax({
type: 'POST',
url: '/get_selected_values',
success: function(response) {
alert('Ok');
draw();
},
error: function() {
alert('Error');
}
});
When you're getting a successful response from this, you're seeing your "OK" alert in the UI, right? However nothing updates in the UI despite you calling on the draw() method?
You won't want to return a render_template from your Flask function in this case. You were already on the right track with returning JSON from your function:
if data:
# return jsonify({'result': True, 'data': data}) # does not work this way
When you return your JSON data, it will be stored in the response variable in your success function. If you're unsure of exactly what's going into that response variable then output its contents with something like alert(JSON.stringify(response)) in the success function of your AJAX request. From here you will see your data returned to your method.
Now you need to decide how you want to use that data to update your <div id="data"> element in your UI. You can do this just using JavaScript with a series of document.getElementById('element_id').innerHTML statements or such-like so that your element is populated with all of the updated data from your response.
This will auto-update the data you wish to have displayed without the need to refresh the page.
Now that you've done that, invoke your draw() function again and it should now use the updated data.
I hope this helps set you down the right path with this one!
AFTER EDIT 1
When you're originally populating <div id="data"> you are using a loop to populate a series of <li> tags in the element with your data.
When you are updating this element with your new data, you are just using .innerHTML to re-populate the parent <ul> element.
Your draw() method is looking to the data stored in the <li> elements.
Are you absolutely certain that, after you perform your update, your <div id="data"> element is in exactly the same (ie. expected) format to work with your draw() method? In that it's still in the structure:
<div id="data">
<ul id="consumed_values">
<li>Your updated data here...</li>
<li>More updated data...</li>
</ul>
</div>
This is the element structure that your draw() method is expecting to find. It's pulling its data in from each individual <li> element in the list. So these are the elements which need to store your updated values.

how to print array object array in html using angualrjs

I am trying to take data from a movie API (TMDB API) and want to display the details of the movie in my html view page.
I got the response from the API but i cannot figure out the way to handle the response that is in array of an object array.
This is my response
{
"page":1,
"total_results":1,
"total_pages":1,
"results":
[{
"vote_count":779,
"id":20453,
"video":false,
"vote_average":7.7,
"title":"3 Idiots",
"popularity":1.963226,
"poster_path":"\/wbE5SRTZFtQxgj2nIo4HJpQDk0k.jpg",
"original_language":"hi",
"original_title":"3 Idiots",
"genre_ids":[18,35,10749],
"backdrop_path":"\/6LnwpadKFRrqam7IfBAi3lNTz6Y.jpg",
"adult":false,
"overview":"In the tradition of “Ferris Bueller’s Day Off” comes this
refreshing comedy about a rebellious prankster with a crafty mind anda
heart of gold. Rascal. Joker. Dreamer. Genius... You've never met a
college student quite like \"Rancho.\" From the moment he arrives at
India's most prestigious university, Rancho's outlandish schemes turn
the campus upside down—along with the lives of his two newfound best
friends. Together, they make life miserable for \"Virus,\" the
school’s uptight and heartless dean. But when Rancho catches the eye
of the dean's sexy daughter, Virus sets his sights on flunking out the
\"3 idiots\" once and for all.",
"release_date":"2009-12-23"
}]
}
I want to display overview and other details that is in results in my html page using angularjs but i cannot figure out how to do that?
This is my js and html code snippet. Where i try this with another API but now it got private so i have to change the API.
function getItems(){
$http({method:'GET',url:"https://api.themoviedb.org/3/search/movie?api_key=9a1750d469929884b1c959126ec22c83&query=" + $scope.search})
.then(function (response) {
// body...
$scope.movies = response.data.results;
console.log(response.data.results);
});
<div class="movie-details col-sm-8" >
<ul class="details">
<li><img ng-src="{{movies.Poster=='N/A' && 'http://placehold.it/150x220&text=N/A' || movies.poster_path}}" class="movie-poster thumbnail"><a class="movie-title" href="http://www.imdb.com/title/{{movies.imdbID}}" target="_blank">{{movies.original_title}}</a>, {{movies.Year}} <span class="reviews">Reviews | Add your own review</span></li>
<li><span>Released On: </span>{{movies.results}}</li>
<li><span>Runtime: </span>{{movies.Runtime}}</li>
<li><span>Genre: </span>{{movies.Genre}}</li>
<li><span>Director: </span>{{movies.Director}}</li>
<li><span>Writers: </span>{{movies.Writer}}</li>
<li><span>Actors: </span>{{movies.Actors}}</li>
<li>{{movies.overview}}</li>
<li><span>Language: </span>{{movies.Language}}</li>
<li><span>Country: </span>{{movies.Country}}</li>
<li><span>Awards: </span>{{movies.Awards}}</li>
<li><span>IMDB Ratings: </span>{{movies.imdbRating}}</li>
</ul>
<br>
<div>
<a class="links" href="https://www.youtube.com/results?search_query={{movies.original_title}}" target="_blank">Watch Trailers!</a>
|<a class="links" href="https://subscene.com/subtitles/title?q={{movies.Title}}&l=" target="_blank">Get Subtitles!</a>
|<a class="links" href="http://www.amazon.in/s/ref=nb_sb_noss_1?url=search-alias%3Ddvd&field-keywords={{movies.Title}}" target="_blank">Buy Online!</a>
</div>
</div>
You have to use ng-repeat in order to show data in your html, further correct the property names that you bind on html. (for example: results to release_date)
(see this screenshot of console log data)
Sample DEMO :
var myApp = angular.module('myApp', []);
myApp.controller('ExampleController', ExampleController);
function ExampleController($scope, $http) {
function callapi() {
$http({
method: 'GET',
url: 'https://api.themoviedb.org/3/search/movie?api_key=9a1750d469929884b1c959126ec22c83&query=3%20idiot'
}).then(function(response) {
console.log(response.data.results[0]);
$scope.moviesData= response.data.results;
})
}
callapi();
}
<script src="https://code.angularjs.org/1.5.2/angular.js"></script>
<div ng-app="myApp" ng-controller="ExampleController">
<ul ng-repeat="movies in moviesData">
<li><span>Released On: </span>{{movies.release_date}}</li>
<li><span>Runtime: </span>{{movies.Runtime}}</li>
<li><span>Genre: </span>{{movies.Genre}}</li>
<li><span>Director: </span>{{movies.Director}}</li>
<li><span>Writers: </span>{{movies.Writer}}</li>
<li><span>Actors: </span>{{movies.Actors}}</li>
<li>{{movies.overview}}</li>
<li><span>Language: </span>{{movies.original_language}}</li>
<li><span>Country: </span>{{movies.Country}}</li>
<li><span>Awards: </span>{{movies.Awards}}</li>
<li><span>IMDB Ratings: </span>{{movies.imdbRating}}</li>
<hr>
</ul>
</div>
It looks like you are not using the results exactly as you should be. For instance you have movies.results but you already set $scope.movies to your return results properties.
Make sure that you are using the properties within the results property that you set movies to.
For example you could access the overview by calling {{movies.overview}} in your HTML

AngularJS, get data from external source and push into array

I'm trying to call an external scrip that gets data from a database, so I can then populate a select dropdown. I've tried this so far, but I get a load of empty li elements. It is the right count of what there should be just nothing showing?
My controller
app.controller('agenciesController', function($scope, $http) {
var url = "/ajax/getAgencies.php";
$http.get(url).success( function(response) {
$scope.agencies = response;
$scope.agenciesArray = [];
angular.forEach(response, function(value, key){
$scope.agenciesArray.push(value);
})
console.log($scope.agenciesArray);
});
})
My HTML
<body ng-controller="Controller">
<div ng-controller="agenciesController">
<ul ng-repeat="agencyName in agencies">
<li>{{agenciesArray.agencyID}}</li>
</ul>
</div>
</body>
UPDATE -
This code is working but not returning only one response but all.
<div ng-controller="agenciesController">
<ul ng-repeat="agencyName in agenciesArray">
<li>{{agencyName}}</li>
</ul>
</div>
agenciesArray is an array. agenciesArray.agencyID will be undefined. that is why you are gettting empty li.
Do you intend to do this?
<ul ng-repeat="agency in agenciesArray">
<li>{{agency.agencyName}}</li>
</ul>
Try this
<ul ng-repeat="agencyName in agencies">
<li>{{agencyName.agencyID}}</li>
</ul>
Reason:Because agencyArray is nothing in the given context

Vue JS - Putting Json on data

I want to put my JSON data into Vue data, and a display, why can't I get to work?
compiled: function(){
var self = this;
console.log('teste');
$.ajax({
url: 'js/fake-ws.json',
complete: function (data) {
self.$data.musics = data;
console.log(self.$data.musics);
}
})
}
<div id="playlist" class="panel panel-default">
<div class="panel-body">
<ul>
<li v-repeat="musics.item" >
{{nome}}
</li>
<ul>
<div>
</div>
I can't get the code to work.. why?
I think the problem is that musics is not initially part of your Vue data, so when you set its value using self.$data.musics = data, Vue doesn't know it needs to watch it. Instead you need to use the $add method like this:
self.$set("musics", data);
From the VueJs Guide:
In ECMAScript 5 there is no way to detect when a new property is added to an Object, or when a property is deleted from an Object. To deal with that, observed objects will be augmented with two methods: $add(key, value) and $delete(key). These methods can be used to add / delete properties from observed objects while triggering the desired View updates.
this refers to the whole Vue object, so musics object is already accessible via this.musics. More info here in the VueJS API reference and here in the VueJS guide, and more on this here.
With that in mind the code should look something like this:
var playlist = new Vue({
el: '#playlist',
data:{
musics: '',
}
methods: {
compiled: function(){
var self = this;
console.log('test');
$.ajax({
url: 'js/fake-ws.json',
complete: function (data) {
self.musics = data
console.log(self.musics);
}
})
}
}
And the view would be something like this:
<div id="playlist" class="panel panel-default">
<div class="panel-body">
<ul>
<li v-repeat="musics">
{{nome}}
</li>
<ul>
</div>
</div>
Also look at the code of this example.
you can do that with vue-resource. Include vue-resource.js into your app or html file and:
{
// GET /someUrl
this.$http.get('/someUrl').then(response => {
// get body data
this.someData = response.body;
}, response => {
// error callback
});
}

Manipulate DOM Element that raises an event

If I have this code:
<li ng-repeat='i in items'>
<a ng-click='doSomething(i.id)'>link</a>
</li>
and this JS:
function doSomething(objId) {
$.ajax({ url: 'myUrl.php', success: successHandler});
}
function successHandler(response) {
// do something with the response
}
The user clicks on the link, which changes class, an AJAX request is made, then a success handler is called (I've omitted the error handler for brevity).
I need some clean way to access the <li> element whose child originated the click event in both functions:
in doSomething() (for example to write "loading..." and add a "loading" CSS class, maybe with ng-class)
in successHandler() (if success, remove "loading..." and remove the class)
What is the best way to achieve this? I've tried:
using data- attributes (I cannot manipulate them in Angular and don't solve the problem)
using global variables (whoa, bad)
using scope variables, like $scope.currentClickedItem
I recommend not to access dom element directly. Best way to do achieve your goal in angular is:
html:
<li ng-repeat='i in items'>
<a ng-click='doSomething(i)' ng-class="{active: i.isActive}">link</a>
</li>
js:
function doSomething(obj) {
$.ajax({ url: 'myUrl.php', success: successHandler.bind(this, obj});
}
function successHandler(obj, response) {
// do anything with the response and object
obj.isActive = true;
}
But anyhow, you want to access dom:
You can use angular $event object to access clicked element. if you need to access <li>, element.parentElement is your friend.
html:
<li ng-repeat='i in items'>
<a ng-click='doSomething(i.id, $event)'>link</a>
</li>
js:
function doSomething(objId, $event) {
var element = $event.target;
$.ajax({ url: 'myUrl.php', success: successHandler.bind(this, element});
}
function successHandler(element, response) {
// do anything with the response and element
}
bind method's first argument can be null instead of this if they do not need to share same scope.
You can manipulate the object rather than the element.
<li ng-repeat='i in items'>
<a ng-class="i.loading ? 'loading' : ''" ng-click='doSomething(i)'>link</a>
</li>
JS
function doSomething(obj) {
obj.loading = true;
var objId = obj.id;
$.ajax({ url: 'myUrl.php', success: successHandler});
}
function successHandler(response) {
// do something with the response
}
I will answer my own question but leaving #CKK's one as "answered".
There's no need to manipulate the element in doSomething() because I can do:
<li ng-class='i.class' ng-repeat='i in items'>
{{ i.message }}
<a ng-click='doSomething(i)'>...</a>
</li>
Javascript:
function doSomething(obj)
{
obj.class='loading-class';
obj.message="Loading...";
// ajax call...
}

Categories