ng repeat in object with dynamic keys - angularjs

I have a problem writing proper ng-repeat for this object. I would like to display all object properties. There is a main array of apps, each app can have a multiple versions and each version can have multiple users.
Here is object json.
"Awesome App 1": {
"1.16": {
"Steve": [
"steve#example.com",
null
],
"Mike": [
"mike#example.com",
null
]
}
},
"Awesome App 2": {
"1.7.0": {
"steve": [
"steve#example.com",
null
]
}
},
...
Problem is that keys are dynamic and I don`t know how to map it in ng-repeat. Thanks for a help.

You can try something like this:
https://plnkr.co/edit/3wMdzrtkpShLgl8mu9sN
$scope.data.json = {"Awesome App 1":
......
};
<ul>
<li ng-repeat="(key, val) in data.json">
App Name: {{key}} <br/>
<span ng-repeat="(key2, val2) in val">
Version: {{key2}} <br/>
<span ng-repeat="(key3, val3) in val2">
User: {{key3}} - {{val3[0]}} <br/>
</span>
</span>
</li>
</ul>

Related

Proper way to show array inside an array with v-for

I am trying to display the values of the text array/object but I am getting an output trying to show me paragraphs for every name inside the array/object.
Link to current result: current result
I am fairly new to vue.js so any tips are welcome!
<template>
<div class="education center">
<div v-if="object.timelines != null">
<template v-for="(time,index) in object.timelines">
<p :key="index">{{ time.schoolyear }}</p>
<div :key="index" v-bind="time" v-for="(text,index) in time.text">
<p :key="text">Degree: {{ text.degree }}</p>
<p>Institution: {{ text.institution }}</p>
<p>Where: {{text.where}}</p>
</div>
</template>
</div>
</div>
</template>
<script>
export default {
el: ".education",
data: function() {
return {
object: {
timelines: [
{
schoolyear: "2016 - 2017",
text: [
{ degree: "Applied Computer Science" },
{ institution: "Thomas More University of Applied Science" },
{ where: "Belgium, Geel" }
]
},
{
schoolyear: "2018 - 2019",
text: [
{ degree: "Business IT" },
{ institution: "HAMK University of Applied Science" },
{ where: "Finland, Hämeenlinna" }
]
}
]
}
};
}
};
</script>
I only want to show text.degree once for schoolyear="2016 - 2017"
It's not completely clear to me what you want, but maybe is it that you want to iterate through the .text array and, for each entry in the array, display both its key and its content. If so, you might try something like:
<p v-for="(entry, index) in time.text" :key="index">
{{Object.keys(entry)[0]}}: {{Object.values(entry)[0]}}
</p>
If you need to worry about title case for the keys, you could either use a computed property to convert the array, or define a method to convert each string.
First of all thanks to Boussadjra Brahim for providing the codepen wich resolved my issue.
I will first rephrase the question and then copy the solution.
The question: I want to print out values from an array inside a javascript object. In my <div>tag is is currently printing trying to print out text.institution for each element in the text array.
resulting in vue.js trying to show <p>Institution: {{ text.institution }}</p>
for degree, institution and where. Giving a browser output of:
<p>Degree:</p>
<p>Institution: Thomas More University of Applied Science"</p>
<p>Where:</p>
for text.where this would change to
<p>Degree:</p>
<p>Institution:</p>
<p>Where: Belgium, Geel</p>
The answer: Yet again a huge thanks to Boussadjra Brahim for showing the solution.
/* eslint-disable vue/require-v-for-key */
<template>
<div class="education center">
<div v-if="object.timelines != null">
<template v-for="(time,index) in object.timelines">
<p :key="index">{{ time.schoolyear }}</p>
<div :key="index" :set="text = time.text">
<p>Degree: {{ text.degree }}</p>
<p>Institution: {{ text.institution }}</p>
<p>Where: {{text.where}}</p>
</div>
</template>
</div>
</div>
</template>
<script>
export default {
el: ".education",
data(){
return {
object: {
timelines: [
{
schoolyear: "2016 - 2017",
text: {
degree: "Applied Computer Science",
institution: "Thomas More University of Applied Science",
where: "Belgium, Geel"
}
},
{
schoolyear: "2018 - 2019",
text: {
degree: "Business IT",
institution: "HAMK University of Applied Science",
where: "Finland, Hämeenlinna"
}
}
]
}
};
}
};
</script>
I changed the text array from square brackets to curly brackets and instead of using a v-for= I changed to a :set=.

How to display states of a country if two specific countries are chosen from a list of countries in Angular ng-repeat

I have a list of countries, and the client has the option to choose two of these. When the client uses the checkbox tick to choose two countries (by clicking on the checkboxes of two countries), we need to display the states in those two countries using ng-repeat.
Can someone please help me with a small example of the unordered lists and how to use ng-repeat in this scenario?
I am new to Angular.
As far as the HTML, something like the below is a very simple example of what you may end up with. You could use two ng-repeats; one for each country selected, and another for each state within each country:
<div ng-repeat="country in countries">
<h1>country.name</h1>
<ul>
<li ng-repeat="state in country.states">
<p>state.name</p>
</li>
</ul>
</div>
You can create checkboxes which add a "checked" property to the countries. And then a repeat which repeats only checked ones.
View
<p>
Choose {{limit}} countries:
</p>
<p ng-repeat="country in countries">
<input type="checkbox" ng-model="country.checked" ng-disabled="(countries | filter:{checked:true}).length >= limit"> {{country.name}}
</p>
<p>
Result
</p>
<div ng-repeat="country in countries | filter:{checked:true}">
<h1>{{country.name}}</h1>
<ul>
<li ng-repeat="state in country.states">
<p>{{state}}</p>
</li>
</ul>
</div>
</div>
Controller
angular.module("app", [])
.controller("mainCtrl", function($scope) {
$scope.limit = 2;
$scope.countries = [{
"name": "Finland",
"states": [
"statename1",
"statename2"
]
}, {
"name": "Sweden",
"states": [
"statename3",
"statename4"
]
}, {
"name": "Norway",
"states": [
"statename5",
"statename6"
]
}];
});
Demo: https://jsfiddle.net/ptfg5xs0/1/

How to filter the array of objects from the the main object value

I am trying to make a filter using an array of object. but I am not getting the answer as per I requested.
the object the one I looping though has 3 steps of arrays. I am trying to filter them and show in the li element but not working. only the first step works for me.
the array is : "Name,SubProjectsandContracts` ( all are nested inside of the main object)
here is my try:
<div class="section filter1">
<ul>
<li ng-repeat="value in values"> {{value.Name}}</li>
</ul>
</div>
<div class="section filter2">
<ul>
<li ng-repeat="value in values | SubProjects"> {{$index}}</li>
</ul>
</div>
<div class="section filter3">
<ul>
<li ng-repeat="value in values | SubProjects | Contracts"> {{value.Name}}</li>
</ul>
</div>
object for sample :
{
"Id": "1",
"Name": "Khalifa International Stadium",
"SubProjects": [
{
"Contracts": [
{
"CompletedPercentage": 0,
"Id": "583",
"Name": "LP/C21/145",
"Phase": null
},
{
"CompletedPercentage": 0,
"Id": "529",
"Name": "KP/B21/134",
"Phase": null
},
{
"CompletedPercentage": 0,
"Id": "575",
"Name": "LP/C21/142",
"Phase": null
}
],
"Id": "2",
"Name": "Energy Center"
},
Live Demo
You need to build the custom filter according to your requirement here. See this example, and let me know if you face any issue with your case. For documentation please check. A more simple example with same approach.
<input type="text" ng-model="search">
<ul ng-repeat="oneauth in authorisations[0]">
<li ng-repeat="entry in oneauth | nameFilter:search">
{{entry.auth.name}}</li>
</ul>
app.filter('nameFilter', function(){
return function(objects, criteria){
var filterResult = new Array();
if(!criteria)
return objects;
for(index in objects) {
if(objects[index].auth.name.indexOf(criteria) != -1) // filter by name only
filterResult.push(objects[index]);
}
console.log(filterResult);
return filterResult;
}
});

Trouble getting objects with ng-repeat

I am having a tough time with ng-repeat using Angular.
My JSON data looks like this
{
"shows": {
"stations": {
"balaton": [{
"name": "Minimal",
"artist": "Sven Tasnadi",
"duration" : "1H"
}, {
"name": "Forest of Love",
"artist": "Bas Ibelini",
"duration" : "2H"
}, {
"name": "Sound of Underground",
"artist": "Potential Badboy",
"duration" : "2H30"
}],
"djradio": [{
"name": "Strickly Electronica",
"artist": "Culptrate",
"duration" : "1H"
}, {
"name": "Sound of Underground",
"artist": "Potential Badboy",
"duration" : "2H"
}, {
"name": "Sound Time",
"artist": "Leona Graham",
"duration" : "2H30"
}]
}
}
}
In my controller, I set the object to a scope.
$http.get('json/show-schedule.json').success(function(res){
$scope.schedule = res.shows.stations;
});
In my HTML,
<div class="schedule-station" ng-repeat="item in schedule">
<div class="schedule-station-logo" style="background-image:url('img/stations/{{balaton}}.png')"></div>
<ul>
<li class="schedule-duration-{{item.duration}}">
<span class="schedule-time">11PM</span>
<span>{{item.name}}</span>
<i><span>{{item.artist}}</span></i>
</li>
</ul>
</div>
Basically, I have a DIV that needs to be created based on how many stations there are in the JSON. Then, I need to get the station name, which is 'Balaton', and 'DJRADIO', this should be placed in my background-image such as balaton.png.
Then the List Item should be repeated based on how many tracks there in that particular station.
I am having a tough time figuring out how to do this, and my attempts are obviously way off.
Try something like this:
<div class="schedule-station" ng-repeat="(station, tracks) in schedule">
<h2>{{station}}</h2>
<div class="schedule-station-logo" style="background-image:url('img/stations/{{station}}.png')"></div>
<ul>
<li ng-repeat="track in tracks" class="schedule-duration-{{item.duration}}">
<span class="schedule-time">11PM</span>
<span>{{track.name}}</span>
<i><span>{{track.artist}}</span></i>
<b>{{track.duration}}</b>
</li>
</ul>
</div>
Check the demo fiddle
So there are a few things to consider here:
1) You have an object containing the stations, where it's a key, val set of items, where the values of the station property is an array of the songs. If the stations were an array, then you could do something like stations.length, but because it's a set of object properties, we need to count them manually, hence the angular.forEach.
$scope.schedule = data.shows.stations;
$scope.stationCount = 0;
angular.forEach($scope.schedule, function(station){
$scope.stationCount++;
});
2) To place each of the songs, we have to nest another ng-repeat so that we can iterate over each of the songs in the array.
3) The ng-repeat on the outside has to be setup for an object, and not an array, as you have in your original html.
I made a plnkr showing how to do everything for you: http://plnkr.co/edit/ca8WxSEvn00rYVfwN82r?p=preview
See ngRepeat documentation
It is possible to get ngRepeat to iterate over the properties of an
object using the following syntax: <div ng-repeat="(key, value) in myObj"> ... </div>
So to you should be able to iterate your collection like this:
<div class="schedule-station" ng-repeat="(stationName, songs) in schedule">
<div class="schedule-station-logo" style="background-image:url('img/stations/{{stationName}}.ng')"></div>
<ul>
<li ng-repeat="item in songs" class="schedule-duration-{{item.duration}}">
<span class="schedule-time">11PM</span>
<span>{{item.name}}</span>
<i><span>{{item.artist}}</span></i>
</li>
</ul>
</div>

Nested checkboxes in AngularJS resource with external options

I have this data structure, search:
{
id: '1',
name: 'Foo'
service_ids:
[
3,
8,
12
]
}
I then have another data structure, services, that matches the ids from service_ids above with the below:
[
{
id: 3,
name: 'Fighter'
},
{
id: 4,
name: 'Typhoon'
},
{
id: 8,
name: 'Kung'
},
{
id: 12,
name: 'Builder'
}
]
I want to display this in a form using AngularJS. The name is fine. I want to display all possible services as checkboxes and if the search has one of the services checked then it is ticked in the checkbox. Something like:
<li ng-repeat="search in searches">
<input ng-model="search.name">
<ul>
<li ng-repeat="service in services">
<input type="checkbox">
{{service.name}}
</li>
</ul>
</li>
I don't know how to link that checkbox to the service_ids and the services. Any help appreciated.
I am using $resource.
Update
Ignore my answer, misread you nesting request.
If anyone needs nesting guidance see below:
The best way to nest in angular that I have found is to create a template which is aware of child items like this:
<script type="text/ng-template" id="tree_item_renderer.html">
<span>{{tag.Name}}</span>
<ul ng-show="tag.Children.length > 0">
<li ng-repeat="tag in tag.Children" ng-include="'tree_item_renderer.html'" ></li>
</ul>
</script>
<ul class="tag-list">
<li ng-repeat="tag in tags" ng-include="'tree_item_renderer.html'" ></li>
</ul>
If I understand your question it should be as easy as:
<input type="checkbox" ng-model="search.service_ids[service.id]">
And you should also get bi-directional binding.
Updated
Just realized search.service_ids is an array not a map. So the solution above is not accurate.
You might want instead to use a filter:
<input type="checkbox" ng-checked="search.service_ids | contains:service.id">
Then
filter('contains', function() {
return function(haystack, needle) {
return haystack.indexOf(needle) >= 0;
}
});

Resources