I have a Library angularJS application and a JSON Data file that contains an array of book's information like this
[
{
"name" : "test1",
"pages": 0,
"author": "author1",
"year": 1940,
"section": "history",
"current": 0,
"description": "bla bla bla",
"bookUrl": "data/book.pdf"
},
{
"name" : "test1",
"pages": 0,
"author": "author1",
"year": 1940,
"section": "history",
"current": 0,
"description": "bla bla bla",
"bookUrl": "data/book.pdf"
}
]
"current" is for the current page of the current book that i'm reading
and there is a "next" and "prev" buttons in the reading view
when i press "next" it adds "+1" to the "current" num page
the question is (How to send this +1 to the "current" in JSON file with PHP?)
I have this PHP code :
<?php
$jsonString = file_get_contents('library.json');
$data = json_decode($jsonString, true);
$data[0]['current'] = 3;
$newJsonString = json_encode($data);
file_put_contents('library.json', $newJsonString);
?>
See the ($data[0]) is for the index of the first book, how do i send to PHP the index of the current book so it updates the "current" data of the current book?
Here is the "next" function :
scope.goNext = function() {
if (scope.pageToDisplay >= pdfDoc.numPages) {
return;
}
scope.pageNum = parseInt(scope.pageNum) + 1;
$http.get("data/insert.php")
.success(function(data, status, headers, config) {
console.log("data inserted successfully");
});
};
And here is the reading Controller :
app.controller('read', ['$scope','books', '$routeParams',function($scope,books, $routeParams) {
books.success(function(data){
$scope.book = data[$routeParams.bookId]
$scope.pdfUrl = data[$routeParams.bookId].bookUrl;
$scope.pdfName = data[$routeParams.bookId].name;
});
//the pdf viewer options
//$scope.pdfUrl = 'data/tohfa12.pdf';
$scope.scroll = 0;
$scope.loading = 'Loading file please wait';
$scope.getNavStyle = function(scroll) {
if(scroll > 100) {
return 'pdf-controls fixed';
} else {
return 'pdf-controls';
}
};
$scope.onError = function(error) {
console.log(error);
};
$scope.onLoad = function() {
$scope.loading = '';
};
$scope.onProgress = function(progress) {
console.log(progress);
};
$scope.currentBookIndex = parseInt($routeParams.bookId);
}]);
I know it's complicated but i really need that , thanks.
How do you expect your application to behave?
You need to send the bookId and the pageNum with your request!
scope.goNext = function() {
if (scope.pageToDisplay >= pdfDoc.numPages) {
return;
}
scope.pageNum = parseInt(scope.pageNum) + 1;
$http.get("data/insert.php", {
param : {
bookId: $scope.bookId,
pageNum: $scope.pageNum
}
})
.success(function(data, status, headers, config) {
console.log("data inserted successfully");
});
};
BTW. By REST design a GET http request should never change a resource. GET is for READING. If you want to update a resource you should use POST, PUT or DELETE
Related
when i run solr, I got output like that, but i need show "response":{"numFound":4,"start":0,"maxScore":0.21373023,"docs"} line and all lines have id
this is my html
<div id="response">
<pre class="syntax language-{{lang}} content"><code ng-bind-html="response.data | highlight:lang | unsafe "></code></pre>
<div id="result">
<a ng-show="response.data" id="url" class="address-bar addressblock" ng-href="{{url}}">{{hostPortContext}}{{url}}</a>
</div>`
this is my query.js that In connection with the result (here "data" is result object)
var url = Query.url(params);
Query.query(params, function(data) {
$scope.lang = $scope.query.wt;
if ($scope.lang == undefined || $scope.lang == '') {
$scope.lang = "json";
}
$scope.response = data ;
$scope.filterdata=$filter('uppercase') ($scope.response);
$scope.url = url;
$scope.hostPortContext = $location.absUrl().substr(0,$location.absUrl().indexOf("#"));
});`
and got this result
{
"responseHeader":{
"zkConnected":true,
"status":0,
"QTime":21,
"params":{
"q":"sed",
"_":"1580536766390"}},
"response":{"numFound":4,"start":0,"maxScore":0.21373023,"docs":[
{
"id":"/home/sama/sama_installer/masternode",
"attr_stream_size":["15732"],
"attr_x_parsed_by":["org.apache.tika.parser.DefaultParser",
"org.apache.tika.parser.txt.TXTParser"],
"attr_stream_content_type":["application/octet-stream"],
"attr_content_encoding":["ISO-8859-1"],
"attr_resourcename":["/home/sama/sama_installer/masternode"],
"content_type":"application/x-sh; charset=ISO-8859-1",
"language":"en",
...
"_version_":1657306606928396288,
"content":" #!/bin/bash\n#installetion sama project on master\n#cheeke exits sama
{
"id":"/home/sama/sama_installer/start.sh",
"attr_stream_size":["290"],
"attr_x_parsed_by":["org.apache.tika.parser.DefaultParser",
"org.apache.tika.parser.txt.TXTParser"],
"attr_stream_content_type":["application/octet-stream"],
"attr_content_encoding":["ISO-8859-1"],
"attr_resourcename":["/home/sama/sama_installer/start.sh"],
"content_type":"application/x-sh; charset=ISO-8859-1",
"content":" #!/bin/bash\nstart-all.sh\nt=$(cat /var/sama/nodelist)\nfor i in ,
"language":"en",
"content_type_type_s":"application",
"content_type_subtype_s":"x-sh",
"url_ss":["start-all.sh",
"zkServer.sh"],
"_version_":1657306608004235264}]
}}
I am Assuming data realated to your Question. You Can fetch data in following manner. If it return undefined it means there is not parameter named 'id' else 'id' is present
var data = {
"responseHeader": {
"zkConnected": true,
"status": 0,
"id": 101,
"QTime": 21
},
"response": {
"numFound": 4,
"start": 0,
"maxScore": 0.21373023,
"id": 102
},
"response1": {
"numFound": 4,
"start": 0,
"maxScore": 0.21373023
}
}
console.log(data.response)
console.log(data.responseHeader["id"])
console.log(data.response["id"])
console.log(typeof(data.response1["id"]) == "undefined") //This way you can check if id is present or not.
if (typeof(data.response["id"]) != "undefined") {
console.log(data.response)
}
I have a little problem with iterating through JSON objects. I have a JSON file which I get with AJAX, I have there 15 objects. In HTML I have a DIV in which are 3 sections: header, body and date. Every 15 sec I should update this sections with data from JSON file.
HTML:
<div class="blog">
<span id="header">
Blog
</span>
<span id="body">
20+ Best Examples of <br>
Coming Soon Page Design
</span>
<span id="date">
May 28, 2013
</span>
</div>
JavaScript:
$(function() {
$.ajax({
url: "news.json",
success: function(result) {
var headCont = $('#header');
var bodyCont = $('#body');
var dateCont = $('#date');
var res = result.news;
$.each(res, function(index, element) {
for (header in res) {
setInterval(function() {
headCont.html(element.header);
}, 15000)
}
});
}
});
});
JSON:
{
"news": [{
"header": "Microsoft is starting a private beta for its iPhone keyboard",
"body": "Microsoft has its own mobile operating system, but that hasn't stopped it from opening a public beta for a new iPhone keyboard.",
"date": "2016-04-14T08:40:23.449Z"
}, {
"header": "Microsoft sues U.S. government over data gag orders",
"body": "Microsoft wants a federal court to invalidate part of a 1986 law that it alleged has been abused by the government when authorities demand customers' data.",
"date": "2016-03-14T08:40:23.449Z"
}]
}
You should never run interval on AJAX
In your case you only call the server once and loop over the same data
Assuming your JSON works with your loop, perhaps you meant
function updateIt() {
var headCont = $('#header');
var bodyCont = $('#body');
var dateCont = $('#date');
$.ajax({
url: "news.json",
success: function(result) {
var res = result.news;
$.each(res, function(index, element) {
for (header in res) {
headCont.append(element.header);
}
});
});
setTimeout(updateIt,15000); // run after success. use always or complete if needed
}
}
If you need to update the DIV every 15 seconds with the list of stories gotten with ONE AJAX call, then you need to loop with
var news,cnt=0,tId;
function render() {
if (cnt >= news.length) {
clearInterval(tId); // OR set cnt to 0 and do not return to re-iterate
return;
}
var item = news[cnt];
$('#header').append(item.header);
$('#body').append(item.body);
$('#date').append(item.date);
cnt++;
}
$(function() {
.
succes: function(result) {
news = result.news;
render(); // run immediately
var tId = setInterval(render,150000); // and schedule next run
}
.
});
result = {
"news": [{
"header": "Microsoft is starting a private beta for its iPhone keyboard",
"body": "Microsoft has its own mobile operating system, but that hasn't stopped it from opening a public beta for a new iPhone keyboard.",
"date": "2016-04-14T08:40:23.449Z"
}, {
"header": "Microsoft sues U.S. government over data gag orders",
"body": "Microsoft wants a federal court to invalidate part of a 1986 law that it alleged has been abused by the government when authorities demand customers' data.",
"date": "2016-03-14T08:40:23.449Z"
}]
}
var news, cnt = 0, tId;
function render() {
console.log(cnt,news[cnt]);
if (cnt >= news.length) cnt = 0; // rerun
var item = news[cnt];
$('#header').html(item.header);
$('#body').html(item.body);
$('#date').html(item.date);
cnt++;
}
$(function() {
news = result.news;
render();
var tId = setInterval(render, 5000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="header"></div>
<div id="body"></div>
<div id="date"></div>
EDIT
Check this example. It itterates over an array of objects and updates the content every 2 seconds:
var result = [
{ header: 'header0', body: 'body0' },
{ header: 'header1', body: 'body1' },
{ header: 'header2', body: 'body2' },
{ header: 'header3', body: 'body3' },
{ header: 'header4', body: 'body4' },
{ header: 'header5', body: 'body5' },
{ header: 'header6', body: 'body6' },
{ header: 'header7', body: 'body7' }
]
i = 0;
var update = setInterval(function() {
if (result[i]) {
$('#header').html(result[i].header);
$('#body').html(result[i].body);
i++;
} else {
clearInterval(update);
}
}, 2000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<h1>Header: <span id="header"></span></h1>
<h1>Body: <span id="body"></span></h1>
I'm trying to use method from my $scope controller, imported from Factory and execute it on onlick method in Ionic based HTML.
I am still getting undefined and I don't know why, because any other variables from $scope are available (like userid). Is this scope hierarchy problem? I read through many articles, but I'm still stuck. Thanks.
Controller:
var mod = angular.module('Baybee.controller.nameList', []);
mod.controller('NameListCtrl', function ($scope, AllNamesList, UidGenerator, $localstorage) {
//importing list of names from Factory and unique user-id
$scope.namesFromService = AllNamesList.getList('AllNamesList');
$scope.userid = UidGenerator;
// test functions which I wasn't able to execute on 'onclick' method. scope.saveName should be that I wanted to use originaly
$scope.saveName = AllNamesList.transferName;
$scope.testb = function () {
console.log('working!');
};
});
Factory:
var mod = angular.module('Baybee.factory.allNamesList',['ionic'])
.factory('AllNamesList', function($localstorage) {
// 3 more list available as variables, here is just one
var AllNamesList = {
names: [
{
"name": "Jakub",
"set": [
"CzechCalendar",
"Top10Cz2015",
"Top50Cz2010"
],
"properties": {
"sex": "male",
"origin": "Hebrew",
"description": "Comes from Hebrew, יַעֲקֹב (Yaʿqob, Yaʿaqov, Yaʿăqōḇ)"
},
"popularity": [
{
"Cz": {
"2011": "10",
"2012": "7",
"2013": "6",
"2014": "6",
"2015": "7"
}
}
]
}
// more names here
]
};
return {
// returns right list with names based on string argument
getList: function(a) {
switch (a) {
case "AllNamesList":
return AllNamesList;
break;
case "loveNameList":
return loveNameList;
break;
case "maybeNameList":
return maybeNameList;
break;
case "noGoNameList":
return noGoNameList;
break;
default:
console.log("Sorry, can't find list with names");
}
},
// I would like to use this function on onlick method to transfer object with name properties to the right list (
transferName: function(name, listFrom, listTo){
// saving both list names into local memory
for (i = 0; i < listFrom.length; i++) {
if (name = listFrom[i]) {
listTo.push(listFrom[i]);
console.log(listFrom);
listFrom.splice(i, 1);
console.log(listTo);
}
else {
console.log('Cannot find: ' + name + ' in ' + listFrom);
}
}
}
}
});
HTML Body:
<body ng-app="baybee">
<ion-pane ng-controller="NameListCtrl">
<ion-header-bar class="bar-energized" >
<h1 class="title" >Baybee</h1 >
</ion-header-bar >
<ion-content >
<ion-list >
<div ng-repeat="names in namesFromService track by $index">
<ion-item ng-repeat="(key, value) in names"
on-swipe-right=""
on-swipe-left=""
//I would like to execute any function from scope here, but Im getting undefined
//onclick="testb()"
//onclick="saveName(name, 'list1', 'list2')"
<h2>{{value.name}}</h2>
<p>{{value.properties.origin}}</p>
</ion-item>
</div>
</ion-list >
</ion-content >
</ion-pane >
</body >
There is mistake in HTML part, I use onclick method, when it should be ng-click.
ng-click="saveName(name, 'list1', 'list2')"
Thanks
i am using the below format to get a JSON object from my localhost. The JSON is pretty complicated and lengthy so , using jquery to populate the HTML is getting complicated.
function processmsg(msg) {
var jobj = JSON.parse(msg);
if (typeof jobj === 'object')
{
// Parse the JSON
}
document.getElementById("messages").innerHTML = globalTag;
}
}
function waitForMsg() {
$.ajax({
type: "GET",
url: "1.json",
cache: false,
timeout: 50000,
success: function (data) {
processmsg(data);
if (!data) {
setTimeout(
waitForMsg,
1000
);
};
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
setTimeout(waitForMsg, 15000);
processmsg("error");
}
});
};
$(document).ready(function () {
waitForMsg();
processmsg("loading");
});
I would like to use the format like {{jobj.entries}}. something like this. This can be done on angularJS. can you guys please suggest me how to do the same in angular ?
i want to query the JSON every 1 min and when the data is found i want to cancel the interval. I dono how to do it in angularjs.
==================update================
i got below code snippet. It is working fine, But how do i stop the url query once the json object is obtained..
var app = angular.module('urlanalyzer', []);
app.controller('jsonController', function($scope, $http) {
$scope.getData = function(){
var url = "{% static "" %}tmp/{{url_hash}}/{{url_json}}";
$http.get(url)
.success(function(data, status, headers, config) {
console.log(data);
});
};
if (!$scope.data){
setInterval($scope.getData, 2000);
}
The issue here is the json object will be available after 3 sec only.
var app = angular.module('urlanalyzer', []);
app.controller('jsonController', ['$scope','$http','$timeout',function($scope, $http, $timeout) {
$scope.getData = function(){
var url = "{% static "" %}tmp/{{url_hash}}/{{url_json}}";
$http.get(url)
.success(function(data, status, headers, config) {
if(!data)
$timeout(function(){
$scope.getData()
}, 2000)
else{
$scope.myData = data.data? data.data:data;
$scope.showError = false;
}
})
.error(function(msg) {
$timeout(function(){
$scope.getData()
}, 2000)
$scope.processMessage(msg)
});
};
$scope.processMessage = function(msg){
if(angular.isString(msg))
$scope.errorMessage = msg;
else if(angular.isObject(msg)){
$scope.errorMessage = msg.message // the property you want;
}
$scope.showError = true;
}
$scope.getData();
}])
HTML:
<div ng-controller="jsonController">
<div ng-show="showError">
{{errorMessage}}
</div>
<div id="myDatacontainer">
//you can bind any propery of your data by using angular direvtives
//look at ng-bing, ng-if etc. directives
{{myData.name}} ...
</div>
</div>
Hope it help.
Consider you have following JSON data stored in a scope variable named data:
$scope.data = {
"array": [
1,
2,
3
],
"boolean": true,
"null": null,
"number": 123,
"object": {
"a": "b",
"c": "d",
"e": "f"
},
"string": "Hello World"
}
Then you write your HTML in the following way like:
<div>
Boolean: {{data.boolean}}
</div>
<div>
Number: {{data.number * 2}}
</div>
<div>
Array:
<p ng-repeat="(key, value) in data.object"> {{key}} : {{value}}</p>
</div>
Another way to bind <div ng-bind="data.string"></div>
Here you can stop your call. You can use enhanced angular service $interval for this:
$scope.getData = function(){
var url = "{% static "" %}tmp/{{url_hash}}/{{url_json}}";
$http.get(url)
.success(function(data, status, headers, config) {
console.log(data);
$interval.cancel($scope.intervalObject); // cancel the interval when data is loaded
});
};
if (!$scope.data){
$scope.intervalObject = $interval($scope.getData, 2000);
}
if (!$scope.data){
setInterval($scope.getData, 2000);
}
since $scope.data is not set it'll continue calling the request(since you are not setting $scope.data anywhere).
Edit: Also, use angularjs $interval since it's the angular way of using setInterval and it keeps track of the $digest cycle
I have such json representation of a post by its id:
http://127.0.0.1:8000/update/1?format=json
{"title": "about me", "content": "I like program", "created": "2014-11-29T18:07:18.173Z", "rating": 1, "id": 1}
I try to update rating by button click:
<button ng-click="click(post.id)">Click me</button>
I have such javascript code:
<script>
var demoApp = angular.module('demoApp',['ngResource']);
demoApp.controller( 'AllPosts', function ($scope, $http)
{
$http.get('/blogpost/?format=json').success(function(data,status,headers,config)
{
$scope.posts = data.results;
$scope.predicate = '-title';
$scope.click = function(post_id, $resource){
var Post = $resource('/update/:PostId ',{PostId:post_id,format:'json'} );
post = Post.get({PostId:post_id}, function() {
post.rating = post.rating+ 1 ;
post.$save();
});
};
}).error(function(data,status,headers,config)
{} )
;})
</script>
Peharps i have mistake because in json i have a single object. But i dont really know
Besides i have such view to have a json by certain post by its id:
class UpdateModel(generics.RetrieveUpdateDestroyAPIView):
lookup_field = 'id'
queryset = BlogPost.objects.all()
serializer_class = BlogPostSerializer
permission_classes = (AllowAny,)
A quick tidy up of your script tag shows that you are only defining the function click if the http call was successful.
I would suggest moving the definition of the click method outside of the success callback.
You may also be running into a race condition that the click function has not been defined before clicking the actual button. Regardless you will want to move that function definition to where the controller is actually created.
Suggested edits (moved click definition outside of http call response):
var demoApp = angular.module('demoApp', ['ngResource']);
demoApp.controller('AllPosts', function($scope, $http, $resource) {
$scope.click = function(post_id) {
var Post = $resource('/update/:PostId ', {
PostId: post_id,
salutation: 'json'
});
post = Post.get({
PostId: post_id
}, function() {
post.rating = post.rating + 1;
post.$save();
});
};
$http.get('/blogpost/?format=json').success(function(data, status, headers, config) {
$scope.posts = data.results;
$scope.predicate = '-title';
}).error(function(data, status, headers, config) {});
})
Updates:
Injected $resource into the controller
Removed $resource from click function params