I'm getting an object as the scope. The object looks like this:
And my controller looks like this:
module.controller('ActiveController', ['$scope','$http',
function($scope, $http) {
$http({
method: 'GET',
url: 'http://localhost:8000/api/order/?format=json'
}).then(function successCallback(response) {
console.log("OK Respone");
console.log(response.data);
$scope.orders = response.data;
}, function errorCallback(response) {
console.log("NO Response");
});
}]);
In the browser console, the object looks like this:
I would like some help to loop out and display whole the object in the .html file. My current code that does not work is currently looking like this:
<div ng-controller="ActiveController">
<div ng-repeat="order in orders">
<p>{{ order.id }}</p>
<p>{{ order.created }}</p>
</div>
</div>
I don't think I need to show my "main" .html file, so I'm not posting it.
The problem is in the controller. Try saving objects in $scope.orders
$scope.orders = response.data.objects;
You can fix this in the view and the controller as well:
In View as:
<div ng-controller="ActiveController">
<div ng-repeat="order in orders.objects"> <!-- note the orders.objects -->
<p>{{ order.id }}</p>
<p>{{ order.created }}</p>
</div>
</div>
In Controller as
$scope.orders = response.data.objects;
As rightly suggested by #ddepablo.
It will work fine.
Related
I am creating an application which will run queries on my store's database, based on what the user enters on the webpage. I have successfully created the backend method. And it successfully returns the response. But I am unable to retrieve the data and display it on my webpage in the form of a dynamic table. I am a bit new to AngularJS, so please bear with me, but any help is appreciated.
StoreController.java
#RequestMapping(value = "/runQuery", method = RequestMethod.GET)
public List<Map<String, Object>> runQuery(#RequestParam(value="query", defaultValue="* FROM items") String statement, Model model) {
List<Map<String, Object>> answer = storeService.executeUserQuery(statement);
model.addAttribute("resultList", answer);
return answer;
}
I tried to model my controller in such a way that it can dynamically take the data received from the Java controller and assign it to the $scope variable.
app.module.js
(function(){
'use strict';
angular.module('app', []);
})();
store.controller.js
angular
.module('app').controller('StoreController', ['$scope','StoreService','StoreController','$q', function ($scope,StoreService, StoreController, $q) {
$scope.runQuery = function () {
StoreService.runQuery($scope.statement)
.then (function (data){
$scope.rows = response.data;
$scope.cols = Object.keys($scope.rows[0]);
},
function error(response){
if (response.status == 404){
$scope.errorMessage = response.data[0];
}
else {
$scope.errorMessage = 'Error displaying result user!';
}
});
}
}
]);
app.service('StoreService',['$http', function ($http,$q) {
this.runQuery = function runQuery(statement){
return $http({
method: 'GET',
url: 'http://localhost:8080/runQuery/',
params: {statement:statement},
headers: 'Accept:application/json'
}).then( function(response){
return reponse.data;
});
}
index.html
<body data-ng-app="app" data-ng-controller="StoreController">
<div class="container">
<form th:action="#{/logout}" method="get">
<button class="btn btn-md btn-danger btn-block"
style="color: #fff; background-color: #e213a2; border-color: #c3c2c0;"
name="registration" type="Submit">Logout</button>
</form>
<div class="panel-group" style="margin-top: 40px">
<div class="panel panel-primary">
<div class="panel-heading">
<span th:utext="${userName}"></span>
</div>
<div>
<form name="queryForm" method="get" data-ng-submit="runQuery()">
<div class="panel-body">
<h3 id="queryLabel">Select Query:</h3>
<textarea id="query" wrap="soft"
placeholder="Please do not enter SELECT with your query, it's added automatically!!" data-ng-model="statement"></textarea>
<button type="submit">Run Query</button>
</div>
</form>
<div class="panel-body" id="results">
<h3 id="queryLabel">Result:</h3>
<table border="1">
<tr>
<th data-ng-repeat="column in cols">{{column}}</th>
</tr>
<tr data-ng-repeat="row in rows">
<td data-ng-repeat="column in cols">{{row[column]}}</td>
</tr>
</table>
</div>
</div>
<div>
<p class="admin-message-text text-center" th:utext="${adminMessage}"></p>
</div>
</div>
</div>
</div>
</body>
The table on the html page, works because I received it from this link
http://jsfiddle.net/v6ruo7mj/1/
But it's not populating the tables with the data received from my backend controller method. I do not have any entities as this is just querying an existing database, so I need not to add any entities.
The issue probably is this line here in the service callback within your controller:
.then (function (data){
$scope.rows = response.data;
// ...
}
try with:
.then (function (data){
$scope.rows = data;
// ...
}
You already return the responses data in your service when calling:
}).then( function(response){
return reponse.data;
});
Aside from your question I should mention that your Spring controller seems to be vunerable to SQL injection. It's in general not a good idea to allow the user to access your database directly. Although I don't know how your StoreService on the backend is implemented. But it seems as if an attacker could easily send a HTTP call to your endpoint and drop your database.
You have a typo in the runQuery function:
app.service('StoreService',['$http', function ($http,$q) {
this.runQuery = function runQuery(statement){
return $http({
method: 'GET',
url: 'http://localhost:8080/runQuery/',
params: {statement:statement},
headers: 'Accept:application/json'
}).then( function(response){
̶r̶e̶t̶u̶r̶n̶ ̶ ̶r̶e̶p̶o̶n̶s̶e̶.̶d̶a̶t̶a̶;̶
return response.data
});
}
}]);
I have a simple JSON file with a "customers" object.
{
"customers": [
{
"firstname": "John",
"lastname": "Doe",
"account": "123456",
"amount": "$121.34",
"period": "13th July - 13th August",
"duedate": "14th September"
},
{
"firstname": "Jack",
"lastname": "Bauer",
"account": "1111222",
"amount": "$142.56",
"period": "11th July - 11th August",
"duedate": "16th September"
}
]
}
Essentially, when a customer visits the page, I want to display his own personal information using Angular JS. So, something like below:
<h2>{{ customers.amount[0] }}</h2>
<p>{{ customers.period[0] }}</p>
<p>{{ customers.duedate[0] }}</p>
my JS file is:
var UtilityApp = angular.module('UtilityApp', []);
UtilityApp.config(['$qProvider', function($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
UtilityApp.controller('mainController', function($scope, $http) {
$http({
method: 'GET',
url: 'https://jsonblob.com/26078b70-6b6f-11e7-a38a-bf689f57642c'
}).then(function (data) {
// create a message to display in our view
$scope.customers = data.customers;
}), function () {
return "Error";
}
});
How can I return all information for customer 1, then customer 2...? Would ng-repeat with a filter be a better approach?
What is a better way to ensure that a customer is looking at his information (and not someone else)? I don't want to use a login here, so I was thinking using a specific URL to visit for customer. Any better idea?
Thanks!
Best and most efficient way would be to get single customer from backend API, so you can ensure security and response is smaller because you don't need to fetch all customers, but if you can't get only one customer then
better would be to filter customer in controller by some key (id, cookie, account etc.)
UtilityApp.controller('mainController', function($scope, $http) {
$http({
method: 'GET',
url: 'https://jsonblob.com/26078b70-6b6f-11e7-a38a-bf689f57642c'
}).then(function (data) {
// create a message to display in our view
$scope.accountId = 'getItSomehow';
$scope.currentCustomer = data.customers.find(x => x.account === $scope.accountId);
}), function () {
return "Error";
}
});
<h2>{{ currentCustomer.amount }}</h2>
<p>{{ currentCustomer.period }}</p>
<p>{{ currentCustomer.duedate }}</p>
ng-repeat with filter would be slowest and vague, don't do it.
Note: have a look at array .find https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/find because it is not supported in old browsers.
You can put your customer information like a table using flex or the <table> tag.
If you want to see the information of your customers you should change your code to this.
<h2>{{ customers.amount[0] }}</h2> // <h2>{{ customers[0].amount }}</h2>
<p>{{ customers.period[0] }}</p> // <p>{{ customers[0].period }}</p>
<p>{{ customers.duedate[0] }}</p> // <p>{{ customers[0].duedate }}</p>
Or using ng-repeat
<div ng-repeat="customer in customers">
<h2>{{ customer.amount }}</h2>
<p>{{ customer.period }}</p>
<p>{{ customer.duedate }}</p>
</div>
But if you want to see the information of a specific customer you should pass an ID as a param in the URL for example wit ui-router.
To get the information of the second customer. Example:
http://www.exampleweb.com/customer/2
check out the ui-router module.
https://github.com/angular-ui/ui-router
You are hitting the wrong URL for requesting the json data from json blob. Make the correct url as https://jsonblob.com/api/jsonBlob/26078b70-6b6f-11e7-a38a-bf689f57642c i.e. https://jsonblob.com/api/jsonBlob/<blobId>.
It will return the JSON data containing customers array then you can use the simple ng-repeat to show the data for both customers. or can extract specific data for the single customers reading the array.
If you want display one particular user at a time then dont use ng-repeat. Simply filter the response data or create a service at server side which give response for particular use by pass parameter.
For now you can filter response
var UtilityApp = angular.module('UtilityApp', []);
UtilityApp.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}
]);
UtilityApp.controller('mainController', function ($scope, $http) {
$scope.customerAccountId = "123456";
$scope.currentCustomer = null;
$http({
method : 'GET',
url : 'https://jsonblob.com/26078b70-6b6f-11e7-a38a-bf689f57642c'
}).then(function (data) {
$scope.customers = data.customers;
$scope.currentCustomer = $(x) => {
return x.account === $scope.customerAccountId
};
}),
function () {
return "Error";
}
});
And Display currentCustomer details :
<div>
<p>{{ currentCustomer.amount }}</p>
<p>{{ currentCustomer.period }}</p>
<p>{{ currentCustomer.duedate }}</p>
</div>
I have changed the URL of http request from https://jsonblob.com/26078b70-6b6f-11e7-a38a-bf689f57642c to https://jsonblob.com/api/jsonBlob/26078b70-6b6f-11e7-a38a-bf689f57642c.
Also, I have modified the response object. It have data object which contains your customers object.
You can use some filter condition to identify the customer.
var UtilityApp = angular.module('UtilityApp', []);
UtilityApp.controller('mainController', function($scope, $http) {
$http({
method: 'GET',
url: 'https://jsonblob.com/api/jsonBlob/26078b70-6b6f-11e7-a38a-bf689f57642c'
}).then(function (response) {
$scope.customers = response["data"]["customers"];
//Logic to identify the customer and then bind to $scope.currentCustomer
$scope.account = "123456";
$scope.currentCustomer = response.data.customers.find(x => x.account === $scope.account);
}, function () {
return "Error";
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="UtilityApp" ng-controller="mainController">
<h1>Customer's Info</h1>
<div>
<h2>Account : {{ currentCustomer.account }}</h2>
<p>Amount : {{ currentCustomer.amount }}</p>
<p>Period : {{ currentCustomer.period }}</p>
<p>DueDate : {{ currentCustomer.due_date }}</p>
</div>
<h1>Binding all customer using ng-repeat </h1>
<div ng-repeat="customer in customers">
<h2>{{ customer.amount }}</h2>
<p>{{ customer.period }}</p>
<p>{{ customer.due_date }}</p>
</div>
</div>
//html
<div ng-repeat="obj in customers track by $index">
<h2>{{ obj.amount }}</h2>
<p>{{ obj.period }}</p>
<p>{{ obj.duedate }}</p>
</div>
//controller
$scope.customers = [
{
"firstname": "John",
"lastname": "Doe",
"account": "123456",
"amount": "$121.34",
"period": "13th July - 13th August",
"duedate": "14th September"
},
{
"firstname": "Jack",
"lastname": "Bauer",
"account": "1111222",
"amount": "$142.56",
"period": "11th July - 11th August",
"duedate": "16th September"
}
];
I am new to Angular and I have this issue that I don't get solved. I have read today alot about good style and $scope soup but I could not find an answer to this.
It is the following, very easy example:
I have a controller with an ng-repeat inside and an input with a change-event.
<div id="searchbar" data-ng-controller="SearchCtrl">
<input id="search" autocomplete="off" data-ng-model="search" data-ng-keyup="getResults( search );" />
<div id="input_results">
<li data-ng-repeat="x in names">
{{ x.Country }}
</li>
</div>
</div>
When I assign some json directly from the controller function everything works fine.
var app = angular.module("myApp", []);
var SearchCtrl = function($scope, $http, HTTPService) {
console.log("Control opened");
$scope.names = [{
"Country": "TEXT"
}];
};
When I try to assign json out of the event, then I receive there "parent is null"
var app = angular.module("myApp", []);
var SearchCtrl = function($scope, $http, HTTPService) {
var _this = this;
console.log("Control opened");
$scope.getResults = function(searchstring) {
console.log("Execute search: " + searchstring);
$scope.names = [{
"Country": "TEXT"
}];
_this.getResults(searchstring, $scope, $http);
};
};
I don't know how I can pass the correct scope to getResults() or how to solve this issue. Additionally I have read that it is best to use dots in model names like SearchStrl.search to avoid shadowing.
I am also confused about the behaviour, when I change $scope.search it works fine inside the getResult() function, but why not with the ng-repeat.
It would be nice if somebody could explain me the reason for this behaviour.
Thank you.
Your ng-repeat code fails to work because he doesn't has an array to repeat on through.the code only creates the array after you activated 'getResults' function.
in your controller you shold have something like this:
app.controller('CTRL1', function($scope){
$scope.names = [{
"Country": "TEXT"
}]; //your array
$scope.getResults = function(search) {
//your search code.
}
})
I can see you're trying to make a list of items with a search. instead of the above code I will suggest you do as followed:
<div data-ng-controller="SearchCtrl">
<input data-ng-model="search" /> <!-- creates a search instance- -->
<div id="input_results">
<!--filter by search model -->
<li data-ng-repeat="x in names | filter: search">
{{ x.Country }}
</li>
</div>
and in your code:
$scope.names = [{
"Country": "TEXT"
}];
I am creating reusable custom directive in angularjs where I am looking to pass fieldName for ng-repeate items as attribute. All my scope is isolated
My part of directive codes as below
<div class="list">
<label ng-repeat="item in items" class="item item-text-wrap">
{{item.City}}
</label>
</div>
In above code I am passing fieldName hard code but I want to pass City (i.e. field name) by attribute
of my custom directive
<custom-select items="deptStations" drop-down-field="City"></custom-select>
in above items are passed by http service from controller
.controller('Ctrl', function($scope, $http) {
$http.get("http://www.xxxx.com/_api/lists/getbytitle('XXX')/items?$select=Id,City_Code,City&$filter=Active eq 1&$orderby=City asc", {
headers: {
Accept : "application/json;odata=verbose"
}
}).then(function(resp) {
$scope.deptStations = resp.data.d.results;
}, function (err) {
console.log(err);
});
});
So idea over here is that I want to pass drop-down-field and I want to pass in my directive. Is it possible, if yes then how ?
i think below code will solve your problem
angular.module("module").directive("customSelect", function(){
return{
scope : {
dropDownField : '#',
items : '='
};
};
});
<div class="list">
<label ng-repeat="item in items" class="item item-text-wrap">
{{item[dropDownField]}}
</label>
</div>
Here is a fiddle: http://jsfiddle.net/a0eLhcbm/
I have a simple setup:
<div ng-app="demo" ng-controller="PageController">
{{ page.time }}
<div ng-controller="UsernameController">
{{ user.name }}
</div>
</div>
There is a function that will, say, get the user.name from somewhere else using ajax, and that function belongs to controller PageController.
Question: Is there anyway I can make the {{ user.name }} within the UsernameController to update itself as soon as the controller PageController receives the information?
Here is my javascript setup:
var app = angular.module( 'demo', [] );
function_that_fetches_for_username = function() {
//Some function that fetch for username asynchronously
};
app.controller( 'PageController', function ( $scope ) {
//Initial data
$scope.page = {};
$scope.page.time = Date();
function_that_fetches_for_username();
//How can I make the UsernameController to update its view from this Controller as soon as this controller receives the information?
});
app.controller( 'UsernameController', function( $scope ) {
//Initial data
$scope.user = {};
$scope.user.name = "";
//How can I automatically updated the $scope.user.name in view as soon as the PageController receives the information about the username?
});
There are probably a lot of ways to solve this problem, my share to this is to use either of the two below:
[1] Create a service that you can share to any part of your application (Controllers, Services, Directives, and Filters).
In relation to your problem, you can simply create a User service that can be shared across your controllers. The solution below assumes that the function_that_fetches_for_username() is a service UserResource that has a method get() that simulates fetching data from a server. The User service is an empty object that is shared across all your controllers.
DEMO
JAVASCRIPT
angular.module('demo', [])
.service('UserResource', function($timeout) {
this.get = function() {
return $timeout(function() {
return {
id: 'w3g45w34g5w34g5w34g5w3',
name: 'Ryan'
};
}, 2000);
};
})
.service('User', function() {
return {};
})
.controller('PageController', function($scope, UserResource, User) {
$scope.page = {
time: Date()
};
UserResource.get().then(function(data) {
angular.extend(User, data);
});
})
.controller('UsernameController', function($scope, User) {
$scope.user = User;
});
HTML
<div ng-app="demo" ng-controller="PageController">
{{ page.time }}
<hr>
<div ng-controller="UsernameController">
<div ng-if="user.name">
{{ user.name }}
</div>
<div ng-if="!user.name" style="color: red">
Waiting for Response...
</div>
</div>
</div>
[2] Use the controllerAs syntax for declaring controllers. Use this type of notation for child controllers to access parent controllers using their aliases.
DEMO
JAVASCRIPT
angular.module('demo', [])
.service('UserResource', function($timeout) {
this.get = function() {
return $timeout(function() {
return {
id: 'w3g45w34g5w34g5w34g5w3',
name: 'Ryan'
};
}, 2000);
};
})
.controller('PageController', function(UserResource) {
var ctrl = this;
ctrl.page = {
time: Date()
};
ctrl.user = {};
UserResource.get().then(function(data) {
angular.extend(ctrl.user, data);
});
})
.controller('UsernameController', function() {
this.getUser = function(user) {
console.log(user);
};
});
HTML
<div ng-app="demo" ng-controller="PageController as PC">
{{ PC.page.time }}
<hr>
<div ng-controller="UsernameController as UC">
<div ng-if="PC.user.name">
{{ PC.user.name }}
</div>
<div ng-if="!PC.user.name" style="color: red">
Waiting for Response...
</div>
<button type="button" ng-click="UC.getUser(PC.user)"
ng-disabled="!PC.user.name">
Access user from Page Controller
</button>
</div>
</div>
You can do one of these for sharing the same value through multiple controllers:
Promote the value to a higher level scope all the interested controllers have access to. Controllers will get it through scope inheritance because angular automatically searches the value through the scope hierarchy.
Whoever gets the value broadcasts it through the higher level scope all the controllers have access to. All the controllers listening for this broadcast will get the value.
you can define your user in pageController(that is parent controller to UsernameController) now whenever you change it in pageController it will also be updated in usernameController
second solution is to have ng-view in parent, and in route use controller for UsernameController
index file
<div ng-app="demo" ng-controller="PageController">
{{ page.time }}
<ng-view></ng-view>
</div>
user.html
<div ng-controller="UsernameController">
{{ user.name }}
</div>
route codee
.when("/user",{
controller:"usernameController",
templateUrl : 'user.html'
})
Third solution is to make a service
.factory("userFactory",function(){
var user = {};
return{
setUser : function(usern){
user = usern;
},
getUser : function(usern){
return user;
},
}
})
now you can get user from service and set to service .