Displaying JSON answer in an html page with AngularJS - javascript

I have no background in JavaScript and/or Angular but I need to use it for a research project. Shortly, I need to display on a webpage the JSON which is the answer from another component.
Here is the flow:
From the user interface clicking on Submit button a JSON file is sent to another component which does something and returns a JSON. This answer JSON should be displayed on a webpage.
The submit button is as follows and happens in the page named page2.html:
<button name="topage1" class="button-submit" ng-click="generateJSON()">Submit</font></button>
The method generateJSON() has the following code:
$scope.generateJSON = function(){
generateIdForComponents();
addRestrictions();
// REST
data = angular.toJson($scope.schema, true);
headers= {
'Content-Type': 'application/json',
'Cache-Control':'no-cache',
'Access-Control-Allow-Origin': '*'
};
$http.post('http://127.0.0.1:5000/re/z3', data, {headers:headers}).
then(function(response) {
console.log("Merge post ", response.data);
$scope.greeting = response.data;
});
}});
The routing is as follows:
app.config(function($routeProvider) {
$routeProvider
.when("/topage1", {
templateUrl : "page1.html",
controller : "page1Controller"
})
.when("/topage2", {
templateUrl : "page2.html",
controller : "page2Controller"
})
.when("/results", {
templateUrl : "outputOffers.html",
controller : "resultsController"
})
.otherwise({
templateUrl : "page1.html",
controller : "page1Controller"
});
});
What code should I write such that the JSON is displayed on outputOffers.html.

I suggest that in the callback of your $scope.generateJSON method, you redirect to the outputOffers results page (where you want to display the response json data) and you pass the json data as a parameter.
Then in your resultsController you can assign the json data (sent as a parameter) to a $scope.greeting variable to use in your outputOffers view.
You need the routeParams service to pass parameters between views and you will need to inject it into your resultsController.
You will also need the $location service in your page2Controller (in order to perform the redirect) so inject it as follows:
myApp.controller("page2Controller", function($scope, $location){...
Your generateJSON method in your page2 controller would look like this:
$scope.generateJSON = function(){
generateIdForComponents();
addRestrictions();
// REST
data = angular.toJson($scope.schema, true);
headers= {
'Content-Type': 'application/json',
'Cache-Control':'no-cache',
'Access-Control-Allow-Origin': '*'
};
$http.post('http://127.0.0.1:5000/re/z3', data, {headers:headers}).
then(function(response) {
console.log("Merge post ", response.data);
//redirect to the outputOffers view, passing the json data as a parameter
$location.path('results').search({jsonData: response.data });
});
}});
resultsController
Firstly inject the $routeParams to your resultsController as follows so we can get any parameters sent with the url (replace myApp with the name of your app):
myApp.controller("resultsController", function($scope, $routeParams){...
Use an anonymous function in the resultsController which checks whether the jsonData parameter exists (which we sent from the page2 controller). If it does exist then we assign it to a $scope.greeting variable
(function() {
if($routeParams.jsonData == null || $routeParams.jsonData === ""){
//If the jsonData is not set or if it doesnt contain a value (i.e is the empty string) then redirect to the page2 view.
$location.path('topage2');
}else{
//the jsonData parameter does exist so assign it to our scope.greeting variable so we can use it in our view.
$scope.greeting = $routeParams.jsonData;
//log the data to make sure it was passed as parameter:
console.log($scope.greeting);
}
})();
Then in the outputOffers.html view you can use the $scope.greeting variable.
For example if the json contains a "title" and a "message" property then we can do the following:
<p>{{greeting.title}}</p>
<p>{{greeting.message}}</p>
Update:
After seeing a snippet of your json in your comment you could do the following to display it:
<div ng-repeat="g in greeting">
<p>id: {{g.id}}</p>
<p>clockspeed: {{g.offer.clockSpeed}} </p>
</div>

One option can be create a service which will contain two functions to store and to fetch the value. The function that stores the value will be placed in 'page2Controller'.
The function that fetches the value will be placed in resultsController.
Find below a short tutorial.
the service should look like this:
app.config(function($routeProvider) {
$routeProvider
.when("/topage1", {
templateUrl : "page1.html",
controller : "page1Controller"
})
.when("/topage2", {
templateUrl : "page2.html",
controller : "page2Controller"
})
.when("/results", {
templateUrl : "outputOffers.html",
controller : "resultsController"
})
.otherwise({
templateUrl : "page1.html",
controller : "page1Controller"
});
});
app.service('greetingService', function() {
this.greeting = '';
this.store = function (greeting) {
this.greeting = greeting;
}
this.fetch = function () {
return this.greeting;
}
});
page2Controller should look like this:
app.controller('page2Controller', function($scope, greetingService) {
$scope.generateJSON = function(){
generateIdForComponents();
addRestrictions();
// REST
data = angular.toJson($scope.schema, true);
headers= {
'Content-Type': 'application/json',
'Cache-Control':'no-cache',
'Access-Control-Allow-Origin': '*'
};
$http.post('http://127.0.0.1:5000/re/z3', data, {headers:headers}).
then(function(response) {
console.log("Merge post ", response.data);
greetingService.store(response.data);
});
}});
});
resultsController should look like this:
app.controller('resultsController ', function($scope, greetingService) {
$scope.greeting = greetingService.fetch();
});
then, somewhere in your 'outputOffers.html' put this:
{{greeting}}

Related

AngularJS not showing $scope

I know this question has been answered but given solutions didn't work for me. Everything looks okey, but the contento between curly brackets it's not showing on screen.
<div ng-controller="Hello">
<p>The ID is {{greeting.ip}}</p>
<p>The content is {{greeting.ip}}</p>
</div>
The controller is the folling:
'use strict';
angular.module('sbAdminApp')
.controller('Hello',['$scope','$http', function ($scope, $http) {
$http.get('http://ip.jsontest.com/')
.then(function (data) {
$scope.greeting = data;
console.log($scope.greeting);
});
}]);
And in my app.js, im declaring this:
.state('dashboard.test', {
templateUrl: 'views/test.html',
url: '/test',
controller: 'Hello',
resolve: {
loadMyFiles: function ($ocLazyLoad) {
return $ocLazyLoad.load({
name: 'sbAdminApp',
files: ['scripts/controllers/helloWorld.js']
})
}
}
})
The JSON URL from where I'm getting the data is this.
And here are the pics with the output from the console:
$scope.greeting = data; This line is wrong.
It should be $scope.greeting = data.data;
EDIT:
Because you are assigning your response from the server to that variable and you need only the data returned from the API call. You response object contains stuff like headers and status code and the data property which actually contains your the data you need like id and stuff. If you want to get the id from your response object you can do it like this: greeting.data.id.
I always name my response variable res or response so not to mess it up. Like this:
$http.get('http://ip.jsontest.com/')
.then(function (res) {
$scope.greeting = res.data;
console.log($scope.greeting);
});
}]);
The problem is you're doing the following:
$scope.greeting = data;
But according to your JSON it should be:
$scope.greeting = data.data;
The data variable holds the whole JSON object, and you want the data key from it.

$window resets my service

I am creating an login page using Angular. After I process my login in the backend, I set the values in MyService from my LoginCtrl and then move to the next page using $window.location.href= 'main.jsp'; . But when I call the values which I set in LoginCtrl from HomeCtrl, the values are empty?
I know that Services are singletons and will maintain the same state throughout the app. But in this case, It jut resets. I think it is because of using $window.location.href. Please help me solve my problem.
This is my service ( MyService ):
app.service('MyService', function() {
var user = {
name: '',
permissions: ''
};
this.getUser = function() {
return user;
}
this.setUser = function(userr) {
this.user = userr;
}
});
This my LoginCtrl: ( I've just posted the http.post part)
$http({
method: 'POST',
url: 'login',
data: JSON.stringify($scope.user),
headers: {
'Content-Type': 'application/json'
}
}).success(function(data) {
if (!("failure" == data)) {
console.log(data);
var user = MyService.getUser();
user.name = data.name;
user.permissions = data.permissions;
console.log(user);
console.log(MyService.getUser());
$window.location.href = 'main.jsp';
// MyService.changeLocation('main.jsp', true);
} else {
$scope.information = "Invalid username/password!"
}
}).error(function(data) {
console.log(data);
});
And this is my HomeCtrl:
app.controller('HomeCtrl', function($scope, $http,MyService) {
console.log(MyService.getUser());
var user = MyService.getUser();
$scope.flashMessage="Hello " + user.name;
});
Here user.name is empty.
You are changing your web page. The angular application is not persisted across the website boundary; remove the alteration to the window.location.href.
In order to simulate page changing in Angular consider using the official router (shipped with Angular 1.4+), ngRoute or Angular UI Router. These solutions use the HTML History Api and fallback to hashbang URLs to emulate the sort of thing you're trying to achieve.
This ends up creating a single-page application, which is what Angular is designed for.
In LoginCtrl, while reaching the success callback, you are not setting the response value(data in your case) to user object in MyService service.
You are getting the user object from the Service by
var user = MyService.getUser();
But setting the values to that object will not set the user object in the Service.
You need to use MyService.getUser(user); to set values in your service and the same will be available in your HomeCtrl
$http({
method: 'POST',
url: 'login',
data: JSON.stringify($scope.user),
headers: {
'Content-Type': 'application/json'
}
}).success(function(data) {
if (!("failure" == data)) {
console.log(data);
var user= {};
user.name = data.name;
user.permissions = data.permissions;
MyService.getUser(user); //set the values for user
var obj= MyService.getUser(); //get the values for user
console.log(obj);
//should display user object
//with respective name and permissions should be available
console.log(MyService.getUser());
$window.location.href = 'main.jsp';
// MyService.changeLocation('main.jsp', true);
} else {
$scope.information = "Invalid username/password!"
}
}).error(function(data) {
console.log(data);
});
UPDATE:
The reason why your code doesnt seem to work is: you are using $window incorrectly to change the route. $window.location.href = 'main.html' is somehow changing the route outside angular's context and hence not running the HomeCtrl. To fix this, you need to do the following:
First, define routes for your angular application (preferabbly using ui-router)
app.config(function($stateProvider){
$stateProvider
.state('login',{
url:'/',
templateUrl:'login.html',
controller:'LoginCtrl'
})
.state('main',{
url:'/main',
templateUrl:'main.html',
controller:'HomeCtrl'
})
.state("otherwise", { url : '/'})
})
Use $location.url('/main'). Notice it is same as the url pattern we defined for state: main. Or better, you should use $state.go('home'); to redirect the user to desirable state
Here's a working plunkr
Hope this helps!

How to pass parameters to a controller when using route?

In my application, am loading views using ngRoute,
.state('ReportViewer', {
url: "/ReportViewer",
controller: 'ReportViewerControl',
templateUrl: "views/Report_viewer.html"
})
I have a search Panel where users can search reports, and when selecting a report, it should route to a different page and load the report inside an iframe. Here is my code when the user select the report,
$scope.goReport = function(report){
$state.go('ReportViewer');
}
I have defined a constant in the config which changes dynamically based on the report selection
.constant('Digin_ReportViewer','http://192.226.192.147:8080/api/repos/%3Ahome%3Aadmin%')
Here i need to pass the 'Report' variable to the ReportViewerControl when the user select the report,
Here is my ReportViewerControl
routerApp.controller('ReportViewerControl', ['$scope', '$routeParams','Digin_ReportViewer',function($scope, $routeParams,Digin_ReportViewer) {
//here i need to append the report url ,
$scope.reportURL = Digin_ReportViewer+routeParams.report ;
$scope.trustSrc = function(src) {
return $sce.trustAsResourceUrl(src);
}
}
]);
you are using ui-router for confiuring routes ,but below in ReportController you are using $routeParams.I hope you have to use $stateParams for that.
routerApp.controller('ReportViewerControl', ['$scope', '$stateParams','Digin_ReportViewer',function($scope, $stateParams,Digin_ReportViewer) {
//here i need to append the report url ,
$scope.reportURL = Digin_ReportViewer+stateParams.report ;
$scope.trustSrc = function(src) {
return $sce.trustAsResourceUrl(src);
}
}
]);
also you have to pass the params from url or in method like this
.state('ReportViewer', {
url: "/ReportViewer",
controller: 'ReportViewerControl',
templateUrl: "views/Report_viewer.html",
params: ['report']
})
Then you can navigate to it like so:
$scope.goReport = function(report){
$state.go('ReportViewer', { 'report':'monthly' });
}
Or:
var result = { 'report':'monthly' };
$state.go('ReportViewer', result);

Setting and getting data value from service in Angular JS

So this is my service that I use to fetch user details.
angular.module('app')
.factory('userDetailService', function($http) {
var userData = {};
function getUserDetails(userId) {
if (userId) {
return $http.get("/users/" + userId).success(function(data) {
angular.copy(data[0], userData);
});
}
}
return {
userData: userData,
getUserDetails: getUserDetails
}
})
Now in Controller 1 that uses this service, I have this bit of code which works fine as I get the relevant data.
$scope.getUserId = function(userId) {
if (userId) {
$scope.userData = userDetailService.userData;
userDetailService.getUserDetails(userId).success(function() {
console.log($scope.userData); //Prints valid user data
});
}
};
After this function executes in Controller 1, I try to do the following in Controller 2:
$scope.userData = userDetailService.userData;
console.log($scope.userData); //Prints null
But $scope.userData is null. Isn't the whole purpose of using a service to share data between controllers? Since I have already set the value of userData in Controller 1, shouldn't I be able to access it in Controller 2?
Weirdly enough, the modal dialog which is the template for Controller 2 is able to access data in the form of {{userData.first_name}} or {{userData.last_name}}. If this works, why is $scope.userData null? What am I missing?
Edit:
Template 1:
<div id="myModal" ng-controller="Controller 1">
<modal-configure-user></modal-configure-user>
<a data-toggle="modal" data-target="#configureUserModal" href="#" ng-click="getUserId(user.id)" data-id="user.id">{{user.first_name + ' ' +user.last_name}}</a>
</div>
Template 2:
<div ng-controller="Controller 2" id="configureUserModal">
</div>
Both are modal dialog windows.
Your approach is not very reliable, since you can't be 100% sure that data has already loaded when you try to access it in the second controller. Instead of assigning user data to variable always invoke getUserDetails method, which returns a promise. Then you just need to cache loaded data to avoid duplicated requests.
angular.module('app')
.factory('userDetailService', function($q, $http) {
var userData;
function getUserDetails(userId) {
if (userId) {
return userData ? $q.when(userData) : $http.get("/users/" + userId).success(function(data) {
userData = data;
return userData;
});
}
}
return {
getUserDetails: getUserDetails
}
});
Wrapping userData into $q.when creates a promise object, which resolves immediately. This is what you need, because service API is now consistent - you always deal with promises.
The usage in both controller then would be:
userDetailService.getUserDetails(userId).then(function(data) {
$scope.userData = data;
});

AngularJS: how should I set the params for $http dynamically?

I am very new with AngularJS. Thank you for answer. My code is as follow:
mainModule.controller('MainController', function($scope, $http) {
$http.get('http://localhost/backend/WebService.php', {params: {entity: 'IndexPageEntity'}}).
success(function(data) {
$scope.intro = data[0].IndexPageContent;
});
$http.get('http://localhost/backend/WebService.php', {params: {entity: 'ExhibitionServiceEntity'}}).
success(function(data) {
$scope.exhibit = data[0].ExhibitionServiceContent;
});
$http.get('http://localhost/backend/WebService.php', {params: {entity: 'ShootingServiceEntity'}}).
success(function(data) {
$scope.shooting = data[0].ShootingServiceContent;
});
});
My html file would be:
<div ng-controller="MainController">
<div>{{intro}}</div>
<div>{{exhibit}}</div>
<div>{{shooting}}</div>
</div>
I believe there must be some ways to improve the above code in order to reduce repetition. What I want is to pass entity parameter to the controller on creation.
Using ng-init to pass parameter is discouraged, according to the documentation. Writing custom directive to pass argument to scope does not work since parameters would be overwrittern.
What is the best practice to set params dynamically for use in $http? Thank you.
You should move all the logic to a service and use a directive. I would suggest you to modify your backend to return the same structured data, instead of IndexPageContent, ExhibitionServiceContent, etc. it should be Content or whatever name you want to use. But for now I've added a replace function to get the name of the content from the name of the entity.
mainModule.factory('webService', function($http) {
var apiUrl = 'http://localhost/backend/WebService.php';
function getContent(params) {
var config = {
'params': params
};
return $http.get(apiUrl, config);
};
return {
getContent: function(params) {
return getContent(params)
}
};
});
mainModule.controller('MainController', function($scope, webService) {
var params = {
'entity': $scope.entity
};
var contentName = $scope.entity.replace('Entity', 'Content');
webService.getContent(params).then(function (data) {
$scope.content = data[0][contentName];
});
});
mainModule.directive('EntityContent', function() {
return {
controller: 'MainController',
replace: true,
restrict: 'E',
scope: {
entity: '#entity'
},
template: '<div>{{ content }}</div>'
};
});
<div>
<entity-content entity="IndexPageEntity">
<entity-content entity="ExhibitionServiceEntity">
<entity-content entity="ShootingServiceEntity">
</div>
Create an object data and send the value for the key inside the object at every call.. Also pass the value for key to be set inside the scope..
E.g.
$scope.makeHttpCall = function(data) {
$http.get('http://localhost/backend/WebService.php', {params: data}).
success(function(data) {
$scope[$scope.key] = data[0][$scope.key];
});
};
you can then call this function as
$scope.key = 'IndexPageContent';
data = {
entity : 'yourValueHere'
};
$scope.makeHttpCall(data);
You can set other values as well inside the scope that are dynamic for each request..
I hope this makes sense to you...

Categories