ng-options default value from external json file - angularjs

I have a select
data-ng-model="layout" ng-options="layout.url as layout.name for layout in layouts"
populated from an external json file:
{
"metaDescription": "My website description",
"metaKeywords": "keyword1, keyword2",
"siteTitle": "My Company",
"pageTitle": "Welcome ",
"layout": [
{ "name": "Cerulean", "url": "cerulean" },
{ "name": "Cosmo", "url": "cosmo" },
{ "name": "Cyborg", "url": "cyborg" }
],
"test": "Lorem ipsum dolor"
}
And a controller
function httpController($scope, $http) {
$http.get('content.json').success (function(data){
$scope.layouts = data.layout;
$scope.layout = $scope.layouts[2];
});
};
The $scope.layout = $scope.layouts[2]; should set as the default value but it does not work.
It seems to be working if the JSON array is in the controller but I need to use it from an external JSON and in this case it does not work!
Any help would be appreciated.

You just need to add .url to your $scope.layout = $scope.layouts[2];
In your $http.get() Do the following.
$http.get('URLToGET')
.success(function(data){
$scope.layouts = data.layout;
$scope.layout = $scope.layouts[2].url; //<--- .url
});
Your HTML will look like this:
<select data-ng-model="layout" ng-options="layout.url as layout.name for layout in layouts">
<option value="">Select Url</option>
</select>
Here is a new updated working example
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope) {
$scope.data = {
"metaDescription": "My website description",
"metaKeywords": "keyword1, keyword2",
"siteTitle": "My Company",
"pageTitle": "Welcome ",
"layout": [
{ "name": "Cerulean", "url": "cerulean" },
{ "name": "Cosmo", "url": "cosmo" },
{ "name": "Cyborg", "url": "cyborg" }
],
"test": "Lorem ipsum dolor"
};
$scope.layouts = $scope.data.layout;
$scope.layout = $scope.layouts[2].url;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<select ng-model="layout" ng-options="layout.url as layout.name for layout in layouts">
<option value="">Select Url</option>
</select>
<label ng-bind="layout"></label>
</div>
</div>
For Some clarification
When you use ng-options, the values of option tags written out by
ng-options will always be the index of the array item the option tag
relates to. This is because Angular actually allows you to select
entire objects with select controls, and not just primitive types.
Refer to a great answer by Ben Lesh for details on ngOptions as well as the ngOptions official docs.

Modify your ng-options like this:
ng-options="layout as layout.name for layout in layouts"
Your ng-options expression is in the following format:
select as label for value in array
Per angular documentation the definition of select is:
The result of this expression will be bound to the model of the parent
element. If not specified, select expression will default to
value.
You are binding the url property to the model not the whole object. That is the problem.

Related

Set certain option of a select

I am trying to update a row in table, so in edit mode I need to fetch the existing data and populate them in a card. Its fine with textboxes but trouble with selects. I cannot get the select to show the existing option fetched.
My mark up:-
<select class="textbox-style4" data-ng-options="obj.text for obj in segment track by obj.value" data-ng-model="u_segment">
</select>
here's how I am initializing the select: -
$scope.segment = [ {
"text" : "B2B",
"value" : "0"
}, {
"text" : "B2C",
"value" : "1"
} ];
And here's how I am trying to set its value (tried two ways) :-
1)
$scope.u_segment = selected.segment;
2)
$scope.u_segment.value = selected.segment;
But it(select) still stays blank, though others (text fields) are populated.
You are selecting obj, so your selected.segment must be the entire object: {"text" : "B2B", "value" : "0"} (for example)
Here is a demo:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
var selected = {
"segment": {
"text": "B2C",
"value": "1"
}
};
$scope.segment = [{
"text": "B2B",
"value": "0"
}, {
"text": "B2C",
"value": "1"
}];
$scope.u_segment = selected.segment;
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<select class="textbox-style4" data-ng-options="obj.text for obj in segment track by obj.value" data-ng-model="u_segment">
</select>
{{u_segment}}
</div>
</body>
</html>
If you don't know the entire object, but only some property of it (like value), you need to search for it (in a loop):
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
var selected = {
"segment": "0"
};
$scope.segment = [{
"text": "B2B",
"value": "0"
}, {
"text": "B2C",
"value": "1"
}];
for(var i=0; i<$scope.segment.length; i++){
if($scope.segment[i].value == selected.segment){
$scope.u_segment = $scope.segment[i];
}
}
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<select class="textbox-style4" data-ng-options="obj.text for obj in segment track by obj.value" data-ng-model="u_segment">
</select>
{{u_segment}}
</div>
</body>
</html>

Access images from local JSON file on the web page in angularjs

Where am i going wrong?
I want to access images from datahl.json file on the web page but unable to access them.Please check the codes and help me.
If possible please refer the solution to plunker editor.
index.html
<div class="col-sm-4" ng-repeat = "hbl in hbls">
<div class="thumbnail" ng-repeat = "h in hbl.data_list"
style="width:100%;">
<img ng-src="{{h.img}}" alt="" style="height:50vh;">
<div class="caption">
<p><strong>{{h.name}}</strong></p>
</div>
</div>
</div>
app.js This is my js codes
var app = angular.module('hostellApp', []);
app.controller('hostellController', function($scope, hblsFactory){
$scope.hbls;
hblsFactory.getHbls().then(function(response){
$scope.hbls = response.data;
});
$scope.sayHello = function(){
console.log("Hello");
}
});
app.factory('hblsFactory', function($http){
function getHbls(){
return $http.get('datahl.json');
}
return {
getHbls: getHbls
}
});
datahl.json This is my local JSON file
`
{
"view_type": 5,
"title": "Hostels By Locality",
"position": 5,
"data_list":
[
{
"img": "https://s3.us-east-2.amazonaws.com/images-city-
teens/IMG_20180526_1139570.8091572935412125.jpg",
"name": "Mahavir Nagar"
},
{
"img": "https://graph.facebook.com/1666751513414902/picture?
type=large",
"name": null
},
{
"img": "https://s3.us-east-2.amazonaws.com/images-city-
teens/cropped1148015742983667713.jpg",
"name": "New Rajiv Gandhi"
},
{
"img": "https://s3.us-east-2.amazonaws.com/images-city-
teens/cropped998427941.jpg",
"name": "Jawahar Nagar"
}
]
}`
The data you get from your JSON file is not an array but an object. This means that you only need one ng-repeat.
Change your first ng-repeat to ng-repeat="h in hbls.data_list"(added an 's' to hbl) and delete your second ng-repeat.
Working plunker: https://plnkr.co/edit/OOd1M1dNFjSB7uaqZZB6?p=preview

Is there a way to escape dot notation in AngularJS groupBy expression?

I am using this AngularJS filter: https://github.com/a8m/angular-filter#groupby
I have a piece of data (JSON) involving key names containing dots, which seems to be mistaken with nested properties.
Is there a way to prevent the filter from parsing the dot notation or an alternate way to specify the name of the field used for grouping ?
Note: I can't change the way data are build from the server.
My code looks like this :
<div ng-repeat="(key, values) in items | groupBy: 'category_id.name'" >
<div class="item-row">
{{key}}
</div>
<div class="badge-row" ng-repeat="item in values">
{{item.name}}
</div>
</div>
And here is the JSON data I get from the server :
[
{
"id": "1",
"name": "test",
"category_id.name": "Main"
},
{
"id": "2",
"name": "foo",
"category_id.name": "Other category"
},
{
"id": "3",
"name": "bar",
"category_id.name": "Test"
}
]
When running this code, at the moment, I am getting 'undefined' as key value.
Angular Filter uses $parse, so that you can order by fields in nested objects
I have a workaround for this problem. If it helps.
Template:
(key, values) in items | groupBy: rawProperty('category_id.name')
Controller:
$scope.rawProperty = function(key) {
return function(item) {
return item[key];
};
};
JS Bin Demo
Hope it helps.

Only show content associated with user

I have a service that does a request,
.factory('movieService', ['$http', function($http) {
return {
loadMovies: function() {
return $http.get('/movies_users.json');
}
};
}])
This is the JSON output and is the result of 2 tables being joined. A user table and a movie table. As you can see the users are associated with 1 or more movies.
[
{"id":1,
"email":"peter#peter.nl",
"movies":[
{
"id":4,
"title":"Creed",
movie_id":"312221"
},
{
"id":5,
"title":"Star Wars: Episode VII - The Force Awakens",
"movie_id":"140607"
}
]
},
{"id":2,
"email":"jan#jan.com",
"movies":[
{
"id":4,
"title":"Creed",
movie_id":"312221"
}
]
}
]
I then have this function in my controller,
movieService.loadMovies().then(function(response) {
$scope.movies = response.data;
});
This stores the data from the service into the movie scope.
If I do,
"ng-repeat" => "movie in movies"
The ng-repeat shows all the movies added by all the users. How would I only show the movies associated with the current user in a view?
This seems to be what you want - let me know if it helps.
Note that you have an extra " on movie_id" that is certainly not helping
angular.module('myApp', [])
.controller('ctrl', function($scope) {
$scope.users = [
{"id":1,
"email":"peter#peter.nl",
"movies":[
{
"id":4,
"title":"Creed",
movie_id:"312221"
},
{
"id":5,
"title":"Star Wars: Episode VII - The Force Awakens",
"movie_id":"140607"
}
]
},
{"id":2,
"email":"jan#jan.com",
"movies":[
{
"id":4,
"title":"Creed",
movie_id:"312221"
}
]
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="ctrl">
<div ng-repeat="user in users">
{{user.email}}
<div ng-repeat="movie in user.movies">
{{movie.title}}
</div>
</div>
<h2>Movies for user 2</h2>
<div ng-repeat="movie in users[1].movies">
{{movie.title}}
</div>
</div>
Found in a quick google search:
How do I filter an array with AngularJS and use a property of the filtered object as the ng-model attribute?
<div ng-repeat="movie in movies | filter {email:'user#email.com'}">
Edit: it looks like you actually have a list of users, so you could do a filter on an ngrepeat on users, then you'd have a nested ngrepeat on movies (unfiltered because they're attached to a user). But depending on how your app actually needs to work you could just filter the data when it comes back and throw out the users you don't need. Which introduces the question, do you have access to the server side code? If so you could filter there and not return data that is associated with a different user in the first place

JSON Angular Array pulling data from 3rd Loop

I am struggling to pull the data from the 3rd loop (Names) in the array below.
Any idea what i am doing wrong?
sample.json
{
"otc": [
{
"name": "Tums",
"language": [
{
"title": "English",
"names": [
{"name": "Tums"},
{"name": "Pepto"}
]
},
{
"title": "China"
},
{
"title": "Germany"
}
,
{
"title": "Mexico"
}
,
{
"title": "India"
}
,
{
"title": "United Kingdom"
}
]
},
{
"name": "Dramamine",
"language": [
{
"title": "title2album1"
},
{
"title": "title2album2"
},
{
"title": "title2album3"
}
]
}
]
}
And this is my index.html
<body ng-app="list">
<div ng-controller="ListCtrl">
<ul>
<li ng-repeat-start="meds in otc">
<strong> {{meds.name}}</strong> //This displays just fine
</li>
<li ng-repeat="lang in meds.language"><em>{{lang.title}}</em></li> //This displays just fine
<li ng-repeat-end ng-repeat="drugs in lang.names">{{drugs.name}}</li> //This doesnt display
</ul>
</div>
<script>
angular.module('list', []);
function ListCtrl($scope, $http) {
$http({method: 'GET', url: 'sample.json'}).success(function(data) {
$scope.otc = [];
angular.forEach(data.otc, function(value, key) {
$scope.otc.push(value);
});
$scope.isVisible = function(name){
return true;
};
});
}
</script>
It looks like your JSON data is a bit incomplete, since you're missing the names key in all of the language objects except for the English one.
Beyond that, your html/angular-view code is a bit off. The ng-repeat's should be nested inside of one-another. This is done by having the opening/closing html tags that contain the ng-repeat directive completely surround the inner <li> tags.
It's a bit hard to tell, but if you want nested lists, you need to add <ul> tags like in my example below.
I believe your index html should look something like:
<ul>
<li ng-repeat="meds in otc">
<strong> {{meds.name}}</strong> //This displays just fine
<ul>
<li ng-repeat="lang in meds.language">
<em>{{lang.title}}</em>
<ul>
<li ng-repeat="drugs in lang.names">{{drugs.name}}</li>
</ul>
</li>
</ul>
</li>
</ul>
The reason why the li ng-repeat tags should be nested is because ng-repeat creates its own isolate scope. Which means that inside of an ng-repeat tag, it only has access to the data made available by the ng-repeat="data in datar" part.
So having:
<li ng-repeat="lang in meds.language"><em>{{lang.title}}</em></li> //This displays just fine
<li ng-repeat="drugs in lang.names">{{drugs.name}}</li> //This doesnt display
as sibling elements, and not the second as a child of the other, the 2nd ng-repeat list does not know what the var lang is. So the drugs in lang.names fails.
Btw, this snippet assumes that the output you want is:
Tums
English
Tums
Pepto
China
Germany
etc
Dramamine
title2album1
title2album2
etc
If you wanted the output as a flat list, you can use the following CSS
ul ul {
padding: 0;
margin: 0;
list-style-type: disc;
}

Resources