PhoneGap: angularjs data appear in browser, not in mobile - angularjs

Like the title say, i'am in the development of an hybrid app using Phonegap + Ionic. I have some angularjs code and the data appear perfectly in the browser but when i test the app in Genymotion (or in a real mobile) doesn't appear.
Here is the html part:
<div class="wod-content-training padding-h4">
<div ng-repeat="sport in training.exercises" class="training no-padding clear-fix roboto-l">
<div class="icon-full w-12" ng-class="sport.image"></div>
<div class="font-9pt relative flexcenter-h-v w-14">{{sport.count}}</div>
<div class="text-right font-9pt relative text-vcenter w-52">< {{sport.name}} ></div>
<div class="icon-full whiteblue-eye w-08"></div>
</div>
</div>
Tell me if you need something about the angularjs code but i think is not important at all. Becouse the code is working in the browser, so the problem is something about PhoneGap (or Cordova) maybe.
Here an image example that show how appear that html part in the browser:
And in the mobile is just empty.
Anybody know something about this? what can be the problem? Sorry if my english is not perfect.
Thanks in advance
UPDATE:
Here is the angularjs to understand how i get the sports part:
app.factory('trainingExercises', ['$q', '$timeout', '$http', function($q, $timeout, $http) {
var exercises = {
fetch: function() {
var deferred = $q.defer();
$timeout(function() {
$http.get('/resources/training.json').success(function(data) {
deferred.resolve(data);
});
}, 30);
return deferred.promise;
}
}
return exercises;
}]);
app.controller('freeWODController', ['$scope', '$location', 'trainingExercises', function($scope, $location, trainingExercises) {
$scope.pageTitle = 'WOD Libre';
trainingExercises.fetch().then(function(data) {
$scope.training = data;
});
}]);
and the training.json here:
{
"exercises": [
{
"name": "Overhead squat",
"image": "green-overhead-squat",
"count": "10"
},
{
"name": "Ring dip",
"image": "whiteblue-ring-dip",
"count": "10"
},
{
"name": "Toes to bar",
"image": "blue-toes-to-bar",
"count": "20"
},
{
"name": "Ring dip",
"image": "whiteblue-ring-dip",
"count": "10"
},
{
"name": "Toes to bar",
"image": "blue-toes-to-bar",
"count": "20"
}
]
}
UPDATE 2:
Thanks to jcesarmobile for recommend me GapDebug tool, which is really good for debugging apps by PhoneGap, and work with Genymotion too!
So now i have what is the problem, but don't know how to solve this at all. This line:
$http.get('/resources/training.json')
That is in www/js/app.js and the training.json is in www/resources/training.json so i tried:
$http.get('../resources/training.json')
But nothing. In the GapDebug i can see the FILE_NOT_FOUND for the training.json becouse the location path that is trying to get is: file:///android_asset/resources/training.json
How to properly set the location path in app.js?
Thanks!

Related

Reading JSON file content using AngularJs

I am trying to read and display publications and permissions section from JSON file below using angularjs. I am trying to display idno and title values from publications node and tou, resolution and terms values from permissions nodes. Bun when I try to run below code I am getting blank page.
Here is my HTML and Js code-
<div ng-controller="rFind">
<p>The ID is {{pubs.idno}}</p>
<p>The content title is {{pubs.title}}</p>
</div>
angular.module('demo',[])
.controller('rFind', function ($scope, $http) {
$http.get('rfind.json').success(function (data) {
$scope.pubs = data.publications;
});
});
JSON File -
{
"location": "US",
"publications": [
{
"idno": "1360-0869",
"workId": "122936490",
"title": "INTERNATIONAL REVIEW OF LAW (1996- )",
"permissions": [
{
"tou": "DIGITAL",
"resolution": "GRANT",
"terms": [
{
"code": "d0214dec",
"description": "This journal title may publish some Open Access articles, which provide specific user rights for reuse."
},
{
"code": "93bfc4ca",
"description": "User may not include copies of portions of this Work in presentations shown to external audiences."
}
]
},
{
"tou": "PRINT",
"resolution": "GRANT",
"terms": [
{
"code": "d0214dec",
"description": "This journal title may publish some Open Access articles, which provide specific user rights for reuse."
}
]
},
{
"tou": "REACTIVELY_SHARE",
"resolution": "GRANT",
"terms": [
{
"code": "d0214dec",
"description": "This journal title may publish some Open Access articles, which provide specific user rights for reuse."
}
]
}
],
"startYear": 1996,
"customMessages": [ ],
"publishers": [ "ROUTLEDGE" ]
}
]
}
Not sure what's wrong with my code. Any help will be appreciated.
Thanks!
Publications is returning as an array, you need to do one of two things - fix the endpoint so it returns an object, or use the Array prototype find to grab the object, or grab the first index if it exists. You're trying to reference the object when it is an array.
$scope.pubs = data.publications[0];
$scope.pubs = data.publications.find(record => record.idno === param.id);
Or you can do a ng-repeat on scope.pubs.
Can you try this?
angular.module('demo',[])
.controller('rFind', function ($scope, $http) {
$http.get('rfind.json').then(function (data) {
$scope.pubs = data.data.publications;
});
});
Thanks all for your responses. This is what finally worked for me -
rf.js
var myApp = angular.module('myApp', []);
myApp.controller('rFind', ['$scope', '$http', function ($scope, $http) {
$http({
method: "GET",
url: "/js/rf.json"
}).then(function mySuccess(response) {
$scope.posts = response.data;
$scope.pubs = response.data.publications;
}, function myError(response) {
$scope.myWelcome = response.statusText;
});
}]);
rf.htm
<body ng-app='myApp'>
<div ng-controller='rFind'>
<p>ID: {{ posts.location }} </p>
<div ng-repeat="pub in pubs">
<p> idn: {{pub.idno}} - {{pub.title}}</p>
<div ng-repeat="perm in pub.permissions">
<p> -> {{perm.tou}} : {{perm.resolution}} </p>
<div ng-repeat="trm in perm.terms">
<p>{{trm.description}}</p>
</div>
</div>
</div>
</div>>
</body>

How to access "Title" from this JSON object, using AngularJS

Cinemalytics API endpoint, which gives a JSON output:
http://api.cinemalytics.com/v1/movie/releasedthisweek?auth_token=[token]&callback=JSON_CALLBACK
How to access "Title" from this JSON object, using AngularJS
[
{
"Id": "b2a1844b",
"ImdbId": "tt0315642",
"OriginalTitle": "Wazir",
"Title": "Wazir",
"Description": "'Wazir' is a tale of two unlikely friends, a wheelchair-bound chess grandmaster and a brave ATS officer. Brought together by grief and a strange twist of fate, the two men decide to help each other win the biggest games of their lives. But there's a mysterious, dangerous opponent lurking in the shadows, who is all set to checkmate them.",
"TrailerLink": "https://www.youtube.com/watch?v=gdwM7xKOph0",
"TrailerEmbedCode": "<iframe width=\"850\" height=\"450\" src=\"https://www.youtube.com/embed/gdwM7xKOph0\" frameborder=\"0\" allowfullscreen></iframe>",
"Country": "IN",
"Region": "BOLLYWOOD",
"Genre": "Drama",
"RatingCount": 16,
"Rating": 3.7,
"CensorRating": "U/A",
"ReleaseDate": "1/8/2016",
"Runtime": 102,
"Budget": 0,
"Revenue": 0,
"PosterPath": "https://s3-ap-southeast-1.amazonaws.com/cinemalytics/movie/F6E428DA299F2ECEED5B4D3B1723A202.jpg"
},
{
"Id": "1e3424cb",
"ImdbId": "tt3777164",
"OriginalTitle": "Chauranga",
"Title": "Chauranga",
"Description": "A fourteen-year-old Dalit boy (Soham Maitra) is growing up in an unnamed corner of India. His dream is to go to a town school like his elder brother (Riddhi Sen) and his reality is to look after the pig that his family owns. His only escape is to sit atop a Jamun tree and adore his beloved (Ena Saha) passing by on her scooter. His unspoken love is as true as his mother’s helplessness who cleans the cowsheds of the local strongman’s mansion, with whom she also has a secret liaison. When the boy’s elder brother comes on a vacation to the village, he soon finds out about his younger brother’s infatuation. The learned elder brother makes him realize the need to express his love and helps him write a love letter.",
"TrailerLink": "https://www.youtube.com/watch?v=Nu50meFTNU4",
"TrailerEmbedCode": "<iframe width=\"850\" height=\"450\" src=\"https://www.youtube.com/embed/Nu50meFTNU4\" frameborder=\"0\" allowfullscreen></iframe>",
"Country": "IN",
"Region": "BOLLYWOOD",
"Genre": "Drama",
"RatingCount": 17,
"Rating": 3.84706,
"CensorRating": "U/A",
"ReleaseDate": "1/8/2016",
"Runtime": 90,
"Budget": 0,
"Revenue": 0,
"PosterPath": "https://s3-ap-southeast-1.amazonaws.com/cinemalytics/movie/083FFED0BC933C2D60E8891B89269EB3.jpg"
}
]
With your current URL
http://api.cinemalytics.com/v1/movie/releasedthisweek?auth_token=<auth_token>&callback=JSON_CALLBACK
you may have cross origin issues. However you can use the (https://crossorigin.me/) service to avoid this issue.
Then, you should request:
https://crossorigin.me/http://api.cinemalytics.com/v1/movie/releasedthisweek?auth_token=<auth_token>&callback=JSON_CALLBACK
Finally, this can be easily used in your AngularJS code.
I've made a demo, using an AngularJS Service and Controller.
(function() {
var app = angular.module("myApp", []);
// Service
app.service("Service", ["$http",
function($http) {
return {
getData: function() {
return $http.get("https://crossorigin.me/http://api.cinemalytics.com/v1/movie/releasedthisweek?auth_token=<auth_token>&callback=JSON_CALLBACK", null, {
responseType: "json"
});
}
};
}
]);
// Controller
app.controller("Controller", ["$scope", "Service",
function($scope, Service) {
$scope.data = [];
$scope.list = function() {
// Calling the getData() function from the Service.
Service.getData().then(function(response) {
$scope.data = response.data; // Store the response in the data variable.
}, function(response) {
console.log(response); // if there is an error...
});
};
$scope.list(); // Call to the function once.
}
]);
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app="myApp">
<div data-ng-controller="Controller">
<ul>
<!-- As you have an array, you should use data-ng-repeat to show the items collection. -->
<!-- Use data-ng-bind to show the Title (One-way data binding). -->
<li data-ng-repeat="item in data" data-ng-bind="item.Title">
</li>
</ul>
</div>
</div>
Hope this helps.
If the JSON was in a variable movies:
movies.map(function (m) {return m.Title;});
See JSbin example.
With querying the endpoint:
$http.get('http://api.cinemalytics.com/v1/movie/releasedthisweek?auth_token=59CD0710AD10858DD65FE815F0181603&callback=JSON_CALLBACK')
.then(function(res) {
$scope.titles = res.map(function (m) {return m.Title;});
});
$scope.titles would hold the extracted titles.
With no other context or code attempts that you have shown, here is what the simple Angular GET request would look like.
angular.module('myApp', [])
.controller('myController', function($http) {
var vm = this;
getObject();
function getObject() {
return $http.get('http://api.cinemalytics.com/v1/movie/releasedthisweek?auth_token=59CD0710AD10858DD65FE815F0181603&callback=JSON_CALLBACK')
.then(function(res) {
vm.object = res.data;
});
});
<div ng-app="myApp">
<div ng-controller="myController as vm" ng-repeat="item in vm.object track by item.Id">
Item {{item.Id}} - Title: {{item.Title}}
</div>
</div>

ng-view not updating upon ng-click

I am using ng-view within my Angular application. within index.html I have a button, When I click on this button I am getting the JSON data, however I cant access my updated scope back into my ng-view template. please examine the code below.
<
div class="row" style="display:none;" id="srhBox" ng-controller="SearchController">
<button
data-channelid="" data-relatedtovideoid="" data-videoduration="" data-videotype="" data-keyword="{{keyword}}"
ng-click="search($event)" class="btn btn-default" type="submit">
</div>
Here is controller
angular.module('kZoneApp').controller('SearchController', ['$location','$scope', 'dataFactory', '$window', '$routeParams', '$rootScope','$http', function ($location,$scope, dataFactory, $window, $routeParams, $rootScope, $http) {
$scope.search = function (evt) {
$location.path("search"); // update ng-view
var keyword = $(evt.currentTarget).attr("data-keyword");
var channelid = $(evt.currentTarget).attr("data-channelid");
var relatedtovideoid = $(evt.currentTarget).attr("data-relatedtovideoid");
var videoduration = $(evt.currentTarget).attr("data-videoduration");
var videotype = $(evt.currentTarget).attr("data-videotype");
var url = 'http://xxxx.com/api/Videos/Search?'
url = url + 'keyword=' + keyword
url = url + '&channelid=' + channelid
url = url + '&relatedtovideoid=' + relatedtovideoid
url = url + '&videoduration=' + videoduration
url = url + '&videotype=' + videotype
$http.get(url).
success(function (data) {
$scope.searchResults = data;
console.log(data) // Yes it shows JSON data
});
}
}]);
and here is code for ng-view template...
<div class="col-md-12 " style="padding-top:5px;">
{{searchResults.nextPageToken}} // This is BLANK
</div>
json....
{
"nextPageToken": "CBkQAA",
"items": [
{
"etag": "\"dhbhlDw5j8dK10GxeV_UG6RSReM/B_XTRBSSmBkwVbCPVJmABe4rJpo\"",
"id": {
"kind": "youtube#video",
"videoId": "n8JEY8PKCcI"
},
"snippet": {
"publishedAt": "2015-06-05T18:51:06.000Z",
"channelId": "UCY48IObMpigEGsBEtfUUepg",
"title": "WWE 2K15 The New Day vs Power Rangers Summer Slam wwe 2k15",
"description": "I created this video with the YouTube Video Editor (http://www.youtube.com/editor)",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/n8JEY8PKCcI/default.jpg"
},
"medium": {
"url": "https://i.ytimg.com/vi/n8JEY8PKCcI/mqdefault.jpg"
},
"high": {
"url": "https://i.ytimg.com/vi/n8JEY8PKCcI/hqdefault.jpg"
}
},
"channelTitle": "Caqueen520",
"liveBroadcastContent": "none"
}
},..... more items
route config.
$routeProvider
.when('/search', {
templateUrl: 'pages/search.html',
controller: 'SearchController'
})
so {{searchResults.nextPageToken}} is empty, even though console.log clearly shows it has value. what could be causing this.
UPDATE
it seems like the problem is.... I have ng-controller="SearchController" for my button and then i am loading the VIEW (ng-view) using the routes, so angular does not update two controllers with same name on the same page....it updates the first controller & ignores the second one.
Though $http takes care of running digest cycle which takes care of two way biding, try adding a timeout using $timeout because it also runs the digest cycle.
$http.get(url)
.success(function (data) {
$timeout(function () {
$scope.searchResults = data;
console.log(data) // Yes it shows JSON data
}, 100);
});
As per your route config, /search view uses the same controller SearchController. So when you load the /search view using $location.path('/search') the controller is reinitialized so $scope.searchResults will be undefined. You will have to have to search login inside a different controller and use that controller in the route config.
OR you can have a hidden partial view and show it only when you have the searchResults using ng-if directive.
So in the main view have this html
<div ng-if="searchResults" class="col-md-12 " style="padding-top:5px;">
{{searchResults.nextPageToken}} // This is BLANK
</div>
And remove the $location.path('/search') from $scope.search method in the SearchController.

setting up ngDialog

Guys I'm new to angular and trying to figure out how to implement a module called ngDialog so that I can have a pop up appear with angular data ect. Right now, I have my controller:
var oflApp = angular.module('oflApp', ['ngDialog']);
oflApp.controller('oflClassCtrl', function ($scope,ngDialog) {
$scope.classes = [
{"class": "ENGLISH I: INTRO TO LITERATURE AND COMPOSITION Sem 2", "href": "../courses/english.php#p1"}, ect
}];
$scope.clickToOpen = function(index){
$scope.selectedClass= $scope.classes[index];
ngDialog.open({template: '../inc/popUp.html'});
};
});
And html:
<table ng-controller="oflClassCtrl">
…
<tr ng-repeat = "selectedClass in classes | filter:searchTxt">
<td><a ng-click="clickToOpen($index)">{{selectedClass.class}}</a></td>
of course i've added the scripts underneath my angular scripts but is there anything else i need for this to work? I'm not sure what's going on but the pop will not show up on click so im sure something is wrong. What am I doing wrong? Thanks friends.
edit: I refactored my js because i was bored and read about doing it this way, but still doesn't work
(function(){
angular.module('oflApp', ['ngDialog'])
.controller('oflClassCtrl', oflClassCtrl)
function oflClassCtrl($scope,ngDialog) {
// $http.get('../courses/coursedata.json');
$scope.clickToOpen = function(index){
$scope.selectedClass= $scope.classes[index];
ngDialog.open({template: '../inc/popUp.html'});
};
$scope.classes = [
{"class": "ENGLISH I: INTRO TO LITERATURE AND COMPOSITION Sem 2", "href": "../courses/english.php#p1"},ect..
];
} //cntrler
})();

Sub-promises in AngularFire - selecting related children by ID?

I have a json collection I've uploaded to my firebase, the sites and tools are related via arrays located in the former that point to keys in the latter
"sites": {
"s001": {
"name": "ACT-105",
"description": "Intro Accounting",
"type": "course",
"thumbnail": "debate",
"toolCount": 4,
"tools" : ["t001","t002","t003"]
},
"s002": {
"name": "ART-201",
"description": "Pottery Lab",
"type": "course",
"thumbnail": "sculpture",
"toolCount": 4,
"tools" : ["t001","t002","t003","t004"]
},
"tools": {
"t001": {
"name": "main-tool",
"title": "Home",
"description": "Main tool",
"thumbnail": "home.jpeg"
},
"t002": {
"name": "announce-tool",
"title": "Announcements",
"description": "System Announcements",
"thumbnail": "announcements.jpeg"
},
I open a url and promise; then grab the current site and its array of related tools in an array, then open another promise to loop through and get all the related tools. From the alert, it appears to only grab one tool then quits.
angular.module("foo", ["firebase"]).
controller("MyCtrl", ["$scope", "angularFire", function($scope, angularFire) {
var dbRef = "https://sampledb.firebaseio.com";
var siteRef = new Firebase(dbRef + "/sites/s003");
var promise = angularFire(siteRef, $scope, "site", {});
var sitetools = [];
promise.then(function() {
sitetools = $scope.site.tools;
alert("tools " + sitetools);
}).then(function () {
var toolList = [];
for (var i=0;i<sitetools.length;i++)
{
alert("tool " + sitetools[i]);
toolList.push(getTool(dbRef,toolId));
}
$scope.tools = toolList;
});
}]);
var getTool = function(dbRef,toolId) {
var toolitem;
var toolRef = new Firebase(dbRef + "/tools/" + toolId);
alert(toolRef);
var promise = angularFire(toolRef, $scope, "tool", {});
promise.then(function() {
alert("found tool " + toolId);
toolitem = $scope.tool;
});
return toolitem;
};
The fiddle is here: http://jsfiddle.net/5n9mj/1/
First of all, you should have got the alerts (3 of them) since the iterations went as expected, but the return of the getTool() function is always null: it returns before the promise is resolved and local tooitem variable is not accessible anymore.
Remember that all Firebase calls are async. Also, this code:
var promise = angularFire(toolRef, $scope, "tool", {});
promise.then(function() {
alert("found tool " + toolId);
toolitem = $scope.tool;
}
will trigger race conditions: $scope.tool is bound with the Firebase and there is no guarantee that it would be bound in a specific order and if there will be enough processor time to push it into your array before another promise is resolved. That's why it's better to listen on the value change using Firebase reference than to use angularFire and explicitly bind it to the scope variable.
I think you overcomplicated the code a little bit, you don't have to create new Firebase references every time you are binding your scope variables (unless you're going to use the reference later) with angularFire: angulerFire can accept String url as it's first param.
http://jsfiddle.net/oburakevych/5n9mj/10/
If I were you I would wrap the Tool functionality into a directive with a separate controller, so that each tool will have it's own scope, something like this:
<ul ng-repeat="toolId in tools">
<li><tool tool-id="{{toolId}}"/></li>
</ul>
var promise = angularFire(siteRef, $scope, "site", {});
promise.then(function() {
$scope.broadcast("event:SITE_INITIALIZED");
});
.controller("MyCtrl", ["$scope", "angularFire", '$timeout', function($scope, angularFire, $timeout) {
$scope.$on("event:SITE_INITIALIZED", function() {
angularFire(siteRef + "/item/" + $scope.itemId, $scope, "item", {});)
});

Resources