AngularJS ng-options from CakePHP Data - angularjs

I have some json data I receive from a cakePHP server. this is a snippet of what is found in my current $scope.catalog.ConstructionMethod ...
[
{
"ConstructionMethod": {
"id": "99",
"title": "All Plywood",
"price": "0.12"
}
},
{
"ConstructionMethod": {
"id": "139",
"title": "Plywood Sides",
"price": "0.05"
}
}
]
I am trying to create a select box like so...
<select ng-model="Project.ConstructionMethod" ng-options=" ... ">
I have tried the following with no success ...
ng-options="item.title as item.ConstructionMethod for item in catalog.ConstructionMethod"
ng-options="item.ConstructionMethod.title for item in catalog.ConstructionMethod"
I am able to iterate through using ng-repeat just fine. :s
<p ng-repeat="item in catalog.ConstructionMethod">item.ConstructionMethod.title</p>
Any pointers or advice would be greatly appreciated... Thank you.

Angular's select requires an ng-model to work.
Try with the following code:
<select ng-model="result" ng-options="item.ConstructionMethod as item.ConstructionMethod.title for item in catalog.ConstructionMethod"></select>
Let me know if it worked :)

Expounding on aleberguer's answer (which pointed out I needed a model) – I was still having a hard time having the correct options selected when staring my app. The whole "using select as and track by don't work together" thing... so this solution not only populated the options but enabled them to be selected when opening the app.
<select ng-model="result" ng-options="item.ConstructionMethod.title for (k, item) in catalog.ConstructionMethod track by item.ConstructionMethod.id"></select>

Related

Filter collection by child

I have the following fictional object which I'm trying to filter:
{
"0":{
"boy":{
"age":"32",
"name":"Daniel Grey"
}
},
"1":{
"boy":{
"age":"23",
"name":"John Doe"
}
}
}
And then, the ng-repeat directive looks like this:
<ul>
<li ng-repeat="person in people">{{person.boy.name}}<li>
</ul>
My question is, how do I filter people by "name"? I've tried:
<input type="text" ng-model="name">
<ul>
<li ng-repeat="person in people | filter:name">{{person.boy.name}}<li>
</ul>
... but nothing happens [ ng-model seems disconnected from the view! ].
Any response is much appreciated!
Thank you!
Updated answer as per OP's updates
Looking at your fiddle, your $scope.people is essentially an array with one big JSON object, with multiple nested boy objects. This is hard to work with. If you have control over the construction of the JSON object, I will suggest converting into an array of multiple JSON objects, which may look something like:
$scope.people = [
{
"name":"Daniel Grey",
"age":"32",
"gender": "male"
},
{
"name":"John Doe",
"age":"23",
"gender": "male"
}
];
Notice how I converted the boy key into the gender attribute.
If you really have absolutely no control over the data structure, you may have to come up with a custom filter to parse through the nested structure.
Take a look at this fiddle. A few things to pay attention to:
I have to specify people[0] in ng-repeat to retrieve the one big JSON object in your array.
The custom nameFilter searches the .boy.name attribute only.
Original Answer
If you want your filter by just name, you will have to specify the specific attributes in your ng-model directive. So in your case, it will be
<input type="text" ng-model="search.boy.name">
<ul>
<li ng-repeat="person in people | filter:search">{{person.boy.name}}<li>
</ul>
But first you will need to fix your JSON object.
UPDATE:
Live demo on fiddle. I did notice that the search-by-name-only filter doesn't work with angularjs 1.2.1, but works with angularjs 1.2.2.

Resolving object dependencies on client using Restangular

I have problems with restoring my entity relations at the (AngularJS) client after retrieving them via REST using Restangular. I searched a lot, but could not find a clean solution. I have some years of programming experience, but I'm quite new to the AngularJS ecosphere and the REST paradigm.
The task
At my Spring Data backend I have two entities, Article and ArticleGroup, in a 1:n relationship. The resulting REST json (via Spring Data Rest) looks like this:
Article
{
"_embedded": {
"articles": [
{
"id": 1,
"name": "A Drink",
"price": 2.90,
"created": null,
"modified": null,
"active": false,
"displayOrder": 0,
"_links": {
"self": {
"href": "http://localhost:8080/articles/1"
},
"articleGroup": {
"href": "http://localhost:8080/articles/1/articleGroup"
}
}
},
...
ArticleGroup
{
"_embedded": {
"articleGroups": [
{
"id": 1,
"name": "Drinks",
"printer": null,
"_links": {
"self": {
"href": "http://localhost:8080/articleGroups/1"
},
"articles": {
"href": "http://localhost:8080/articleGroups/1/articles"
}
}
},
...
Now I want to display a tabgroup containing the articleGroup.name as the tab's label and a table of the articles in this articleGroup as its content:
<tabset>
<tab ng-repeat="group in articleGroups" heading="{{group.name}}">
<table class="table">
<tr ng-repeat="article in group.articles">
<td ng-click="increase(article)">{{article.name}}</td>
<td>{{article.price | currency }}</td>
...
</tr>
</table>
</tab>
</tabset>
I retrieve the articleGroups easily in my AngularJS controller using Restangular:
Restangular.all('articleGroups').getList()
.then(function(groups) {
$scope.articleGroups = groups;
});
This works fine and the tabs show up nicely. Now I can do so for the articles as well, but here I come upon the problem which I'm dealing with for days now.
The problem
How can I filter the articles for their articleGroup so every portion of articles appears in the right tab? What is the right expression in the ng-repeat above where I just put "group.articles" as a placeholder now?
This sounds very easy, but my problem is that I have no operational identification of an Article's articleGroup to filter the right articles in the ng-repeat for each tab. What I tried:
using the self.href as an id à la article._links.articleGroup.href == articleGroup._links.self.href, but this doesn't work as you can see in the JSON above those two links are set up differently
adding (database) ids to the JSON, but of course an article does not contain the id of its articleGroup, but only the link relation
looping through articleGroups and retrieving each group's articles into an array with the articleGroup.id as the key, but I can't get this to work out as I either get undefined errors by JavaScript or infinite loops
Help
Before I continue fiddling along for hours, it would be great if you could give me hints on which direction to take and what a "clean" and methodologically sound approach to the task would be. How can I bring articles and their corresponding group back togehter?
It seems like such an easy (and frequent) problem, but I tried for hours and days to get it running and fear I'm missing something. I looked at many examples but none of them helped me to have a breakthrough.
I'm happy to provide any further information as needed. Thanks a lot in advance!
Well, I solved it. It turned out that I got lost in the handling of asynchronous requests, especially between having a data object itself and a promise for a request, i.e. placeholders which provide access to the data as soon as it is available - very well explained in this post.
Restangular always returns promises. So I came up with the following solution which works exactly as I wanted to:
For the controller code:
Restangular.all('articleGroups').getList()
.then(function(groups) {
$scope.articleGroups = groups;
for(i=0;i<groups.length;i++) {
$scope.articles[groups[i].id] = groups[i].getList("articles")
}
});
So when the articleGroups arrive from the server, I walk through all of them and put them into the array $scope.articles with the articleGroup.id as key. Notice that group[i].getList("articles") returns a promise for the articles relation. With Restangular's $object property, I receive the articles data array in the ng-repeat:
<tabset>
<tab ng-repeat="group in articleGroups" heading="{{group.name}}">
<table class="table">
<tr ng-repeat="article in articles[group.id].$object | orderBy:'id':false ">
<td>{{article.name}}</td>
<td>{{article.price | currency }}</td>
</tr>
</table>
</tab>
</tabset>
Now, all articles of the selected articleGroup's tab are displayed on the tab. While this seems fine, I'm still not sure if this is the best solution in terms of style or performance. But at least it's a step ahead. Comments very welcome.

Angular JS - Filtering based on checkbox groups (AND & OR conditions)

I am using angularjs for one of my project. I am trying to implement a filtering functionality.
I am constructing the filter check boxes using the code below
<div class="checkbox" ng-repeat="incidentType in keywords.incidentType">
<label><input type="checkbox" value={{incidentType}}>{{incidentType}}</label>
</div>
The result is shown in image below
On checking or unchecking the check boxes, I need to create a object like below. Based on this json object I will send a request to server to fetch the matching data.
{
"application": [
"Athena",
"EWS"
],
"incidentType": [
"Publishing Failure",
"Security Failure"
]
}
Any idea on how can this be achieved in angularjs. Any help is much appreciated.
for something like this, you can use an object like what you want to send as the model, then bind it to the data in your ng-repeat. I let you check here first : http://jsfiddle.net/DotDotDot/gcEJH/
I've taken your sample code and I just added a controller with an object ($scope.checked ) which I use for the ng-model in each checkbox
$scope.checked={application:{}, incidentType:{}};
then, in the HTML
<div class="checkbox" ng-repeat="incidentType in keywords.incidentType">
<label><input type="checkbox" ng-model='checked.incidentType[incidentType]' ng-true- value='{{incidentType}}'>{{incidentType}}</label>
</div>
The ng-model part tells angular to put the value in the incidentType part of the object, under the kay corresponding to the value. This won't give you the exact same object, but you will have something like :
{
"application": {
"Athena": false,
"EWS": true,
"EWindows": true
},
"incidentType": {
"Publishing Failure": true,
"Security Failure": true
}
}
which is actually pretty close, and from which you can create your request (or recreate the same object you wanted easily)
Hope this helps, have fun
=)

Angular ng-repeat filter with predicate function not works as expected

This is my first time playing with AngularJS, and actually, I'm following the getting-started tutorial. It came to my mind that I would tweak the tutorial scripts to my understandings, by just adding a little that was not in the tutorial.
Basically, the phone object used in the tutorial was:
{
"age": 1,
"id": "motorola-xoom",
"imageUrl": "img/phones/motorola-xoom.0.jpg",
"name": "MOTOROLA XOOM™",
"snippet": "The Next, Next Generation..."
}
What I was trying to do was to add an auto populated select box for order the list:
<select ng-model="orderProp">
<option ng-repeat="(key, value) in phones[0]" value="{{key}}">
{{labels[key]}}
</option>
</select>
and added a model labels to the controller:
$scope.labels = {
"name": "Phone name",
"snippet": "Description",
"age": "Newest",
};
It was working as expected, except that I only wanted to filter the 3 properties above, so I think it would be easy to add a custom predicated function for filtering like this:
$scope.isPhonePropFilterable = function (propName) {
console.log('it DOES NOT get here!!!');
return propName == 'name' || propName != 'snippet' || propName != 'age';
};
and added this to the ng-repeat
<option ng-repeat="(key, value) in phones[0] | filter:isPhonePropFilterable" value="{{key}}">
To my suprise, it was not as easy as I thought, my filter function was not called.
See it here: plunker
Did I do anything wrong?
edited: ng-repeat filter supports filtering array only, not object. The filter function returnes if array param is not an array...
Well, it was my fault. Ng-repeat filter supports array only, it did only mention array in the docs. And checking the filter function, it returned if array param is not an array....

AngularJS filter on empty string

I have a simple Angular filter setup between a select and a list. When a user selects an item from the dropdown, the list is updated to show the matching result. The problem is that I have a "Select..." option first in the dropdown with no value, and when that is the selected value, all items are shown. I suppose that makes sense, but I want the opposite. If the selected option has no value, I don't want to show the list. Here are some relevant bits, followed by a link to a full fiddle:
The dropdown:
<select class="world-list" ng-model="selectedWorld" ng-options="world.worldId as world.worldName for world in allWorlds">
<option value="">Select...</option>
</select>
The list:
<ul class="unstyled" id="charList">
<li ng-repeat="char in characters | filter:selectedWorld">
{{char.charName}} - {{char.charRace}} {{char.charClass}}
</li>
</ul>
And here is a link to the full fiddle, which contains my JSON structures that drives all this: http://embed.plnkr.co/6XUmC5efO0Y1BRNLRUig
What I'm trying to do is rather simple, and I'm pretty new to Angular so I'm sure I'm missing something obvious. Checked the Jabbr room, nobody on. :(
Anyway, thanks for any and all help!
One way to accomplish this is to filter by specific properties of the iteration object:
<ul class="unstyled" id="charList">
<li ng-repeat="char in characters | filter:{worldId: selectedWorld}">
{{char.charName}} - {{char.charRace}} {{char.charClass}}
</li>
</ul>
Plunker
I noticed in your code "script.js" you don't seem to be accounting for the blank option.
I did not test this (I probably should prior to posing this answer), but it should work by placing the "blank" option within your script.js.
app.controller('WorldCtrl', function ($scope, $http) {
$scope.allWorlds = [{
worldId: "",
worldName: ""
},
{
worldId: "b8ee0530-744b-463e-9428-23178f6c7bff",
worldName: "World 1"
},
{
worldId: "81211982-5613-4f9c-b704-7b6fa35faf84",
worldName: "World 2"
},
{
worldId: "df41208e-e8d2-46c9-8299-8f37632a51f8",
worldName: "World 3"
}];
$scope.characters = [{
charClass: "Rogue",
charName: "Vaes",
charRace: "Human",
worldId: "b8ee0530-744b-463e-9428-23178f6c7bff"
},
{
charClass: "Warrior",
charName: "Azash",
charRace: "Orc",
worldId: "b8ee0530-744b-463e-9428-23178f6c7bff"
},
{
charClass: "Mage",
charName: "Anele",
charRace: "Ogre",
worldId: "81211982-5613-4f9c-b704-7b6fa35faf84"
}];
});

Resources