I'm attempting to use ng-grid to display a table of data. However, I'm confused as how to place the data into the angular array to display, as examples show from angular-ui that this is the way to go. Below is a service defined for a rails api call
app.factory('ProviderMedicalService', ['$resource', function($resource) {
function ProviderMedicalService() {
this.service = $resource('/api/provider_medical_services/:providerMedicalServiceId', {providerMedicalServiceId: '#id'});
};
ProviderMedicalService.prototype.all = function() {
return this.service.query();
};
return new ProviderMedicalService;
}]);
this snippet of code was taken from a tutorial that integrates rails with angular. the $resource is the json data that is made from a custom rails api call. I'm assuming the return new ProviderMedicalServices returns the json data
(function() {
app.controller('ModalDemoCtrl', ['$scope', 'ProviderMedicalService', '$resource', '$modal', function($scope, ProviderMedicalService, $resource, $modal) {
$scope.provider_medical_services = ProviderMedicalService.all();
In the controller that wraps the table, the tutorial states that the $scope.provider_medical_services helps us extend the api later down the road.
currently my json data is displaying properly, except that it is not being formatted into the table format because of my setup.The following code is just what i'm trying to attempt, and i understand that the data should be inside the controller passed to the array
<div class="gridStyle" ng-grid="gridOptions">
<ul>
<li ng-repeat="service in provider_medical_services">
<p>{{service.name}} {{service.cash_price | currency}} {{service.average_price | currency}}</p>
<p></p>
<p></p>
</li>
</ul>
</div>
basically, my question is how do i pass from the factory into the array like this example?
$scope.myData = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},
{name: "Jacob", age: 27},
{name: "Nephi", age: 29},
{name: "Enos", age: 34}];
$scope.gridOptions = { data: 'myData' };
})
edit for image because cant post image in comments
I'm guessing that instead of
$scope.gridOptions = { data: 'myData' };
you'll want
$scope.gridOptions = { data: 'provider_medical_services'};
I'll give you my example on passing the factory data
Javascript:
fruit = angular.module("fruit", []);
fruit.factory("Fruit", function() {
return {
fruits: [
{name: "Bananas", description: "Yellow and peely"},
{name: "Canteloupe", description: "Tell if its ripe by smelling them"},
{name: "Cherries", description: "Dont try to make jam out of sweet ones"},
{name: "Strawberries", description: "Picking them is murder on your back"},
{name: "Tomatoes", description: "People used to think they were poisonous" }
]
};
});
fruit.controller("FruitCtrl", function($scope, Fruit) {
$scope.fruits = Fruit.fruits;
});
HTML:
<!DOCTYPE html>
<html ng-app="fruit">
<head>
<meta name="description" content="Factory example" />
<script src="http://code.jquery.com/jquery.min.js"></script>
<link href="http://getbootstrap.com/2.3.2/assets/css/bootstrap.css" rel="stylesheet" type="text/css" />
<link href="http://getbootstrap.com/2.3.2/assets/css/bootstrap-responsive.css" rel="stylesheet" type="text/css" />
<script src="http://getbootstrap.com/2.3.2/assets/js/bootstrap.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body ng-controller="FruitCtrl">
<ul>
<li ng-repeat="fruit in fruits">{{fruit.name}}</li>
</ul>
</body>
</html>
edit in response to OP's comment below:
eg:
fruit.factory('Fruit', function($resource){
return $resource('http://localhost/folder1/fruitData.json');
});
Also need to inject the dependency of ['ngResource'] in the angular module
Also try this:
[To handle arrays with the $resource service, you can use the query method]
var fruitData= $resource('http://localhost/folder1/fruitData/');
$scope.items = fruitData.query();
Related
When using ng-repeat which approach has better performance? (assuming there are a large number of users)
Approach 1: Filter in Controller
<div ng-repeat="user in users | showBlocked">
<strong>{{user.id}}</strong>
<span>{{user.name}}
</div>
HTML code in template
$scope.users = [
{ id: 1, name: 'alex', isBlocked: true},
{ id: 2, name: 'john', isBlocked: true}
];
JavaScript code in Controller
showBlocked is a filter which returns a list of blocked users
.filter('showBlocked', function() {
return function(users) {
return users.filter(user => user.isBlocked);
}
});
Approach 2: Reassigns users list
<button ng-click="reassignUser(1)">reassign user</button>
<div ng-repeat="user in users">
<strong>{{user.id}}</strong>
<span>{{user.name}}
</div>
HTML code in template
$scope.reassignUser = function (userId) {
if (userId === 1) {
$scope.users = [{id: 1, name: 'alex', isBlocked: true}];
}
// in this case just assigns a single user
};
CodePen Demo: ng-repeat filter vs reassign binding
Do let me know if you need any additional information.
ng-repeat is evaluated on every $digest cycle, making it extremely slow with two-way data-binding due to $dirty checking. The best solution is to use one-way data-binding with {{:: data}} syntax.
But in your example it is indeed better to re-write the array rather than to filter it. The use of filters will work slower, due to each filter creating a sub collection of the original list. However, this can be resolved differently, by hiding the data with ng-show. Here is a post about the complex solution, but you can consider this simple example:
angular.module('myApp', []);
angular.module('myApp').controller('Ctrl', ['$scope', function($scope) {
$scope.users = [{name:"John", "id":0},
{name:"Adam", "id":1},
{name:"Ado", "id":2},
{name:"Chris", "id":3},
{name:"Heather", "id":4},
{name:"Stan", "id":5}];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp" ng-controller="Ctrl">
ID: <input ng-model="query" />
<ul>
<li ng-repeat="user in users" ng-show="([user.id] | filter:query).length">
{{user.name}}
</li>
</ul>
</div>
I'm a new developer and im trying the framework Dojo-Toolkit and especially d-grid .
So i follow the tutorial (http://dgrid.io/tutorials/1.0/hello_dgrid/) here is my index :
<html>
<head>
<meta charset="utf-8">
<title>Tutorial: Hello dgrid!</title>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/resources/dojo.css">
<link rel="stylesheet" href="djgrid.css">
<link rel="stylesheet" href="claro.css">
</head>
<body class="claro">
<div id="grid"></div>
<!-- load Dojo -->
<script src="dojo/dojo.js" data-dojo-config="async: true"></script>
<script src="dojoconfig.js"></script>
<script>
require([ 'dgrid/Grid', 'dojo/domReady!' ], function (Grid) {
var data = [
{ first: 'Bob', last: 'Barker', age: 89 },
{ first: 'Vanna', last: 'White', age: 55 },
{ first: 'Pat', last: 'Sajak', age: 65 }
];
var grid = new Grid({
columns: {
first: 'First Name',
last: 'Last Name',
age: 'Age'
}
}, 'grid');
grid.renderArray(data);
});
</script>
</body>
</html>
So when i run on "localhost/DOJO/index.html" i get this error :
http://localhost/DOJO/dgrid/Grid.js Failed to load resource: the server responded with a status of 404 (Not Found)
I dont understand why it search on this location ... and also i get 2 :
Error: scriptError(…)
If someone can tell me how that work that ll be lovely :)
Even if the problem seems solved, this answer will clarify Ken's comments and help other people who try to integrate DGrid to Dojo.
Your code require a dgrid/Grid module the same way it require the dojo\domReady
require([ 'dgrid/Grid','dojo/domReady!'], ...);
so your dgrid folder have to be at the same level as your dojo folder.
DOJO
app
dgrid
dijit
dojo
dojox
In your dojoConfig.js, you should have a line like :
packages: ['dojo', 'dijit', 'dojox', 'app', 'dgrid'],
I am pulling in a JSON file using Angular's $http, but I can't get the formatting right to use ng-repeat for an array of data.
For brevity's sake, here is a sample piece of what I'm working with...
{
name:"Pete",
phone: {
brand: "Nexus",
OS: "Android",
contacts: [
"Alexis",
"Billy",
"Chuck",
"Danny"
]
}
}
Then my ng code is
function($scope, $http) {
$http.get('/my/url')
.success(
function(data){
$scope.contacts = data.phone.contacts;
and my HTML is
<div ng-repeat="names in contacts">
{{names}}
</div>
Only it isn't returning anything. I feel like I am missing a set of [] somewhere?
In JSON:
conAtacts: [
"Alexis",
"Billy",
"Chuck",
"Danny"
]
On view:
<div ng-repeat="names in contacts">
{{names}}
</div>
conAtacts != contacts
Also, you have missed one bracket in JSON.
Should be:
{
name:"Pete",
phone: {
brand: "Nexus",
OS: "Android",
contacts: [
"Alexis",
"Billy",
"Chuck",
"Danny"
]
}
}
Can it be reasons of issue?
Your problem could simply be because you didn't respect the widely recommended practice of the 'point' when you use values that can evolve in AngularJS.
Create an object in the scope :
$scope.dataScope = {}
then in your method
function($scope, $http) {
$http.get('/my/url')
.success(
function(data){
$scope.dataScope.contacts = data.phone.contacts;
and in your html
<div ng-repeat="name in dataScope.contacts">
{{name}}
</div>
Thanks everyone for the as always quick responses. This was a case of sleep deprivation and overthinking things on my part and I left out the ng-controller for the div that the ng-repeat was in.
<div **ng-controller="myCtrl"** ng-repeat="names in contacts">
{{names}}
</div>
I have an Angular factory called Model which is shared across multiple controllers.
Basically this Model encapsulate properties and helpers methods.
I'm trying now to bind this model with my view and I have a strange behaviour, The nested objects of Model and the array of objects are not bind properly.
I think this issue is caused by the fact that i'm trying to modify an object inside an other object by reference. Maybe i have lost the context for the nested elements ?
How can i solve this problem ?
Here is my app :
var app = angular.module('plunker', []);
app.factory('Blog', function() {
function Blog(id) {
this.load(id);
}
Blog.prototype = {
name: "",
description: [{
value: ""
}, {
value: ""
}, {
value: ""
}],
website: {
name: "",
url: ""
},
load: function(id) {
},
helper1: function() {
// implementation
},
helper2: function() {
// implementation
}
// many other helpers...
}
return Blog;
});
app.controller('MainCtrl', function($scope, Blog) {
$scope.model = new Blog(12);
});
And finally my view
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.2.x" src="https://code.angularjs.org/1.2.22/angular.js" data-semver="1.2.22"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Name <input ng-model="model.name"></p>
<div ng-repeat="line in model.description">
Description line {{$index}} <input ng-model="line.value">
</div>
<p>Website name <input ng-model="model.website.name"></p>
<p>Website url <input ng-model="model.website.url"></p>
<p>Result : {{ model | json }}</p>
</body>
</html>
To illustrate the problem, i have created a plunker example
When entering the values in the input fields, the Model is not updated with the changes. Only the field name is updated
Thanks in advance
Services are instanced by Angular and then a reference of them is injected where ever it is asked for.
Just change the code as following
var app = angular.module('plunker', []);
app.factory('Blog', function() {
return {
name: "",
description: [
{value: ""},
{value: ""},
{value: ""}
],
website: {
name: "",
url: ""
},
helper1: function() {
// implementation
},
helper2: function() {
// implementation
}
// many other helpers...
}
//return new Blog();
});
app.controller('MainCtrl', function($scope, Blog) {
$scope.model = Blog;
});
There is a slight difference in way in which services, factories and provider works. I hope you are clear on that other wise read this excellent article
http://tylermcginnis.com/angularjs-factory-vs-service-vs-provider/
NEW plunkr
http://plnkr.co/edit/FGOcPWVMeFDSyVtmv8Xd?p=preview
The factory exposes a new method using which you can create new instances of Blog.
I think its also because JSON filter is implemented you are not able to see all the values.
Because decription and website and url are in proto of the object, it's not displaying it.
I added a button for logging the model, you can see in the console that the value is changed
Edit 2
Q: I don't understand why the JSON filter is not displaying the values ?
A: I think it could be how its implemented, may be to make it light weight. Otherwise it has to walk through it's entire prototype chain
Q: Why the values are placed into the proto because of the nature of Blog ?
A: its because you add the values in the Blog's prototype and not inside Blog itself. It's how prototypical inheritence works in javascript. The advantage is think when you have to create 1000s of blog's instances. Now each instance can have the same methods and properties or to make it light weight, each instance can share the same object which is in its proto.(think of base class in OO language)
Read this for more clarity
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain
Blog here is a service that should be created by a factory. Your factory should return the new instance / a value / or a function.
You don't create an instance of the Blog that was injected to your controller, what is injected should already be the only instance available to everything that will be injected to others.
Hence, services are singleton (created by the factory).
Trying to teach myself AngularJS and am stuck on a tutorial trying to build a simple shopping cart. I cannot for the life of me figure out why my {{}} angular tags are not displaying the data in the view, rather they are displaying the literal string (i.e. {{item.price | currency}}) Any insights? I'm worried the code isn't referencing the angular library, but the source is correct - the library is saved as angular.min.js .
Please help!
`
<html ng-app='myApp'>
<head>
<title>Your Shopping Cart </title>
</head>
<body ng-controller='CartController'>
<h1> Your order</h1>
<div ng-repeat='item in items'>
<span>{{item.title}}</span>
<input ng-model='item.quantity'>
<span>{{item.price | currency}}</span>
<span>{{item.price * item.quantity | currency}}</span>
<button ng-click="remove($index)">Remove</button>
</div>
<script type="text/javascript" src="angular.min.js"></script>
<script>
function CartController($scope){
$scope.items = [
{title: 'Paint pots', quantity: 8, price: 3.95},
{title: 'Polka dots', quantity: 17, price: 12.95},
{title: 'Pebbles', quantity: 5, price: 6.95}
];
$scope.remove = function(index){
$scope.items.splice(index, 1);
}
}
</script>
</body>
</html>`
When you set a value to ng-app (like ng-app="MyApp"), Angular.JS will expect you to have something like var myModule = angular.module("MyApp", []).
It will look for controllers only inside that, using myModule.controller() method (or can be directly after the module call). A global function will not work.
So, you have 2 options:
Replace <html ng-app="MyApp"> with <html ng-app>
Creating a module:
angular.module("MyApp", []).controller("CartController", function($scope) {
/// ...
});
Note that if you are using Angular.JS 1.3, you have to use method 2, as the global scope function way was removed in that version.
It is because CartController is just a plain function. You have to add it as a controller under the myApp module
angular.module("maApp", []).
controller("CartController", function ($scope) {
$scope.items = [
{title: 'Paint pots', quantity: 8, price: 3.95},
{title: 'Polka dots', quantity: 17, price: 12.95},
{title: 'Pebbles', quantity: 5, price: 6.95}
];
$scope.remove = function(index){
$scope.items.splice(index, 1);
}
})
I think you are trying this example from Angularjs Book, in which they have clearly mentioned that we are not initializing app for every example, you need to initialize your app. or simply ignore app, start coding from controller. when you mention ng-app="sample" you need to bootstrap that in order to work with controllers directives and everything that you use. In case if you dont want to initialize then you can simply leave ng-app="" blank. Here is working example [fiddle][1]
[1]: http://jsfiddle.net/kaLropns/