Ionic / Angular.js $scope is not passing the value without ng-repeat - angularjs

I have a a controller that generates $scope.product = response.data
In my html template if type {{ product }} it shows the requested metadata in an array including the id and name. However, unless I go through the ng-repeat do ng-repeat='item in product' it won't print id and an name even though I have only one record.
For example {{ product.id }} and {{ product.name }} can be displayed only as {{ item.id }} and {{ item.name }}
I have even tried $scope.product.id = response.data.id and $scope.product.name = response.data.name
Use Case:
Print the product name and other information on a card
Use product.id to take other actions e.g. add to cart.

$scope.product is an array. So it doesn't have any attribute named id or name. Its unique, first element is an object that does have those attributes. So, if you know your array has a single element, what you needs is $scope.product[0].id and $scope.product[0].name.
An array is like a box. A box doesn't become an egg if it contains a single egg. It's still an egg. And trying to fry the box won't lead to a very tasty result. You still need to get the unique egg out of the box and fry the egg.
That said, your backend should probably not return an array containing one product if the service is supposed to return a single product. It should return the product itself.

Related

How to sort a dynamic select list in AngularJS

I have a page in an AngularJS single page application that displays data from multiple tables in my database by reading metadata about the table structure. When a field is a lookup to a foreign key it automatically creates a select drop-down list. Everything is working except I can't get the list to sort by name. It is sorting by the primary key ID field which is usually an int type. Below is the controller script that loads the options list in the model and the view script that displays the select control and tries to sort the items. Can you tell me how to redo this so that it will work? I have also tried with and without the single quotes in the orderBy clause and I have tried using toString() in the orderby clause, but nothing has worked.
// controller script
var responseData = responseFK.data;
angular.forEach(responseData, function (item)
{
columnOptions = columnOptions.concat({ "ID": item[columnNameFK], "Name": item[columnNameFK_Name] });
});
column.COLUMN_OPTIONS = columnOptions;
// view script
<select ng-switch-when="select" ng-options="item.ID as item.Name for item in x.COLUMN_OPTIONS | orderBy: 'item.Name'" ng-model="x.COLUMN_VALUE" ng-required="x.REQUIRED" required></select>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
Try to use orderBy: 'Name', just a property name without item. So your view script should now be:
<select ng-switch-when="select" ng-options="item.ID as item.Name for item in x.COLUMN_OPTIONS | orderBy: 'Name'" ng-model="x.COLUMN_VALUE" ng-required="x.REQUIRED" required></select>

Using md-select, pass the entire object of an ng-repeat item, not just a string

I have made a form with Angular Material that uses a dropdown list to choose from an array of book objects, with names and IDs, for the ultimate purpose of trading it for another book in my collection. Here is what my typical trade object looks like:
var tradeItem = {
wanted: {
user: 'barryjohnson',
bookId: 'foo1bar2'
},
offered: {
user: 'dangraham',
bookId: 'bar7baz8'
},
};
I want to save the entire object to my ng-model in my select menu, so I want the ng-repeat to refer to the entire array object. This way I can make a simple subsequent request to my database.
At the moment it is only saving the title, which is what have inside my md-option tag.
Here is my view:
md-dialog(aria-label='Trade', ng-cloak='')
form
md-toolbar
.md-toolbar-tools
h2 Propose a Trade
span(flex='')
md-dialog-content(style='max-width:800px;max-height:810px; ')
.md-dialog-content
p Which of your books would you like to trade for '{{userClickedBook.title}}'?
p {{selected}}
md-input-container.md-block
label(for="mySelect") Your Books
md-select(name="mySelect", ng-model='selected')
md-option(ng-repeat="book in usersBooks") {{book.title}}
div(layout='row')
md-button(ng-click='cancelDialog()', style='margin-right: 20px;') Cancel
md-button.md-primary(ng-click='save()', ng-disabled='myForm.$invalid', layout='', layout-align='center end') Ok
So, how can I bind the entire object, so that $scope.selected is like the above object tradeItem, instead of just a single string (the content of md-option)?
Won't this work for you?
<md-option ng-repeat="book in userBooks" ng-value="book">
{{book.title}}
</md-option>

Can't get Angular-xeditable Editable-Select to Select the current item when it is bound to a nested JSON object

I can't get the Angular-xeditable Editable-Select to Select the current item when it is bound to a nested JSON object. Data all saves fine, but it just doesn't show up the currently selected item in the Select box, which is driving me nuts, as I am sure I am missing something obvious. I have created a JSFiddle here:
http://jsfiddle.net/NfPcH/1031/
This is the code:
<span editable-select="data.organisation.OrganisationType"
e-ng-options="type.Name for type in data.types">
{{data.organisation.OrganisationType.Name}}
</span>
These are the 2 data objects:
$scope.data.organisation = {
"Id":1,
"Name":"My Organisation",
"OrganisationType":{"Id":2,"Name":"Internal"}
}
$scope.data.types = [
{"Id":1,"Name":"Client"},
{"Id":2,"Name":"Internal"},
{"Id":3,"Name":"Cold"}
]
It works fine when I bind it to the ID within the Nested Object, but then it only changes the Id in my nested object, and I then have to manually filter and change the Name part of the object, which works, but I am sure there must be a better way.
When the item is selected $data is loaded with the id of the item selected. You can use this to retrieve the value after the selection is made.
<span editable-select="data.organisation.OrganisationType"
e-ng-options="type.Name for type in data.types">
{{ findTypeName($data) || data.organisation.OrganisationType.Name}}
</span>
You can then define findTypeName in your controller
$scope.findTypeName = function(id) {
var found = $scope.data.types.filter(function(t){
return (t.Id === id);
});
return found.length ? found[0].Name : null;
};
The trick resides on using the object on the select's ng-options (e.g. 'obj as obj.title') and not a property of the object, so that when an item gets selected, it will assign the whole object to the model and not the property.
The problem with this approach is, that you cannot just compare objects (because comparing an object always compares their reference, not the "contents", so that obj1 == obj2 will never be true, unless they are exact the same object), so the other trick needed here is to use track by <some-id-property> on the ng-options. So your editable would look like this:
<span editable-select="data.organisation.OrganisationType"
e-ng-options="type as type.Name for type in data.types track by type.Id">
{{data.organisation.OrganisationType.Name}}
</span>
Beware that on your JSFiddle you're using a very old version of angular (where track by is not supported), so I created a new one using 1.2, which is the oldest angular version supporting track by:
http://jsfiddle.net/NBhn4/170/

AngularJS not able to include markup in IDs?

I have an array of 3 items and want them to be "ng-repeated"
<li ng-repeat="item in obj.items id="testobj{{testobj.number}}">
</li>
When I look at the page, it appears that the id of the "li" is just "testobj" for all 3 items and not testobj1 testobj2 testobj3 like I was expecting. What is the issue?
Your ng-repeat attribute is missing a final ".
The {{ }} binding is probably coming back with no data and so being treated as if it was an empty string. I see no reference to testobj (the scope variable) anywhere outside of your binding. Is this defined, or should your id read id="testobj{{item.number}}" or something similar?

Exact text filtering while using selection box in angularjs

I have an selection box with some status, based on the change of the status, the item should be iterated but the issue is the angularjs filter functionality not matching the exact text.
HTML
<body ng-controller="sampleController">
<div>
<select ng-model="test" ng-change="getfilter()">
<option ng-repeat="item in list">{{item.status}}</option>
</select>
<ul>
<li ng-repeat="item in list | filter:test">{{item.name}}</li>
</ul>
<div>{{test}}</div>
Controller
function sampleController($scope){
$scope.list = [
{name: "item1", status: "shipped"},
{name: "item2", status: 'Partially Shipped '}
];
$scope.getfilter = function(){
}
}
jsbin : http://jsbin.com/amuwol/2/edit
when i select 'shipped' status i need to get only 'item1' but currently i am getting both 'item1' and 'item2'. I just defined the getfilter function and stopped there since i didnt get idea to proceed further.
Please provide me the solution to proceed further
The filter does work correctly. That is not the cause of the issue that you face.
When you select shipped in the select tag, the reason why the second option is also shown is because the status of the second item contains the word "shipped" - "Partially Shipped". Moreover, you have chosen the case insensitive option.
You have some choices:
Use a different status, something like a number that indicates if the item is shipped or partially shipped. Ensure that no sub-character or number occurs in more than one status. That way, selecting one option will indeed filter out the non-relevant items.
The preferred option - pass a third parameter to the filter. This third parameter will tell the filter if it should be case sensitive or not. So you can use something like:
<li ng-repeat="item in list | filter:test:true">
The "true" parameter tells Angular to be case sensitive. This will fail if instead of Partially Shipped" you change the case to "partially shipped" - that is, the lowercase "shipped" is used instead of the uppercase.
Bin
EDIT: As pointed out below, the setting of "true" parameter to allow the filter to be case sensitive is not supported currently in the stable released of AngularJS
You'll need to implement your own filter because angular's default filter uses toLowerCase(). sth. like
filters.filter('exactString', function() {
return function(string, term) {
return ('' + string).indexOf(term) > -1;
}});
JsFiddle for angular 1.0.7: http://jsfiddle.net/alfrescian/7sMQ8/

Resources