Angular2 Iterating ngFor JSON-File - arrays

I´m fairly new to Angular2, and i want to read out a json file. It´s working, that I get the file from a REST-Client, i can save the file in a local variable in a component. Now I´m trying to read properties (Array) with ngFor, but this isn´t working.
Here´s the html:
<div *ngFor="let categories of tasks.tasks">
{{categories}} --> Display name of categorie (epg, recs)
<p *ngFor="let task of categories">{{task.text}}</p>
</div>
And the JSON-File:
{
"tasks": {
"epg": [{
"text": "\\\\...\\Daten\\Videos\\Aufnahmen"
}, {
"text": "C:\\Users\\...\\Desktop"
}],
"recs": [{
"text": "\\\\...\\Daten\\Videos\\Aufnahmen"
}, {
"text": "C:\\...\\Junias\\Desktop"
}]
}
}
Hope someone can help me ;)

Consider
z={
"tasks": {
"epg": [{
"text": "\\\\...\\Daten\\Videos\\Aufnahmen"
}, {
"text": "C:\\Users\\...\\Desktop"
}],
"recs": [{
"text": "\\\\...\\Daten\\Videos\\Aufnahmen"
}, {
"text": "C:\\...\\Junias\\Desktop"
}]
}
Modify your JSON as
let a=this.z.tasks;
this.z = Object.keys(a).map(function(k) { return a[k] });
Here is a plunker

Related

Using ng-if and ng-repeat correctly

I have a rudimentary understanding of AngularJS and have a couple (possibly stupid) questions about ng-if and ng-repeat.
If I have a ng-repeat that looks like this:
For all containers without titles, would the ng-repeat produce those containers and not show them? Or do they simply don't exist? The reason I ask is I've tried to replace ng-if with ng-show, but it does not produce the same outcome of "hiding" containers that do not have titles.
Is there a way to code a ng-if to say if the next container has no title, then do something. I tried something like ng-if="item.title=='' && $index+1", without any luck.
Any suggestions?
My data looks like this:
"_sections": [{
"_bootstrap_cells": 6,
"_count": 2,
"visible": true,
"columns": [{
"fields": [{
"name": "type_of_account",
"type": "field"
}, {
"name": "routing_transit_number",
"type": "field"
}]
}, {
"fields": [{
"name": "type_of_payment",
"type": "field"
}, {
"name": "check_digit",
"type": "field"
}]
}],
"caption": "Direct Deposit",
"id": "b456b9d2137ac340177c36328144b0ef"
}, {
"_bootstrap_cells": 12,
"_count": 1,
"visible": true,
"columns": [{
"fields": [{
"name": "account_number",
"type": "field"
}, {
"name": "account_title",
"type": "field"
}, {
"name": "financial_institution_name",
"type": "field"
}]
}],
"caption": "",
"id": ""
}
}]
The first section has two columns and a bootstrap cell value of 6 for each column, the second section only has one column and a bootstrap cell of 12. Since the second doesn't have a caption, I want it to be appended to the first section, but keep both sections' bootstrap formatting.
If containers is an array then it does not have a title property. You need to check the title on each item.
Also note that ng-if will not hide the content, but remove it or not insert it into the DOM. The counterpart of ng-show is ng-hide.
angular.module('appModule', [])
.controller('MyController', [function() {
this.containers = [{
aaa: 1,
title: 'One'
}, {
aaa: 2,
title: ''
}, {
aaa: 3,
title: 'Three'
}]
}]);
angular.bootstrap(window.document, ['appModule'], {
strictDi: true
});
<div ng-controller="MyController as myCtrl">
<div ng-repeat="item in myCtrl.containers track by $index">
<div ng-if="item.title!=''">{{$index}}. {{item.title}}</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>

angularjs: extending directive then make modifications

I am working in ServiceNow and am trying to extend an ootb directive, then make some modifications to a couple functions. So far I've figured out how to extend the directive:
function (spModelDirective){
return angular.extend({}, spModelDirective[0], {
templateUrl:'lbl_custom_template.xml'
});
}
Within this directive, there's a function called getNestedFields that I would like to make edits to:
function getNestedFields(fields, containers) {
if (!containers)
return;
for (var _container in containers) {
var container = containers[_container];
if (container.columns) {
for (var _col in container.columns) {
var col = container.columns[_col];
for (var _field in col.fields) {
var field = col.fields[_field];
if (field.type == "container" && container.caption != "")
getNestedFields(fields, [field]);
else if (field.type == "checkbox_container")
getNestedFields(fields, field.containers);
else if (field.type == "field" || container.caption=="")
fields.push(formModel._fields[field.name]);
}
}
}
}
}
Can someone provide some guidance on what the correct syntax for this would be?
More information
Our team cloned the ootb widget-form and am trying to create a custom layout. Basically, we want each form section to be it's own tab much like the back-end form instead of one long form, which is what the ootb widget-form currently does. In the very first line of the sp-variable-layout template, it shows:
<fieldset ng-init="$last ? execItemScripts() : null" ng-show="isContainerVisible(container)" ng-repeat="container in containers">
The ng-repeat of container in containers considers each form section as a separate container (which is perfect), BUT it also considers any splits as a separate container as well. So for example, if my form's layout looks like this:
This will create two tabs: one that has every field within the begin and end splits AND a separate tab with everything after the end split. The JSON object that is created looks like this:
{
"_bootstrap_cells": 6,
"_count": 2,
"visible": true,
"columns": [{
"fields": [{
"name": "type_of_account",
"type": "field"
}, {
"name": "routing_transit_number",
"type": "field"
}]
}, {
"fields": [{
"name": "type_of_payment",
"type": "field"
}, {
"name": "check_digit",
"type": "field"
}]
}],
"caption": "Direct Deposit",
"id": "b456b9d2137ac340177c36328144b0ef",
"scope_name": "x_dnf_table"
}, {
"_bootstrap_cells": 12,
"_count": 1,
"visible": true,
"columns": [{
"fields": [{
"name": "account_number",
"type": "field"
}, {
"name": "account_title",
"type": "field"
}, {
"name": "financial_institution_name",
"type": "field"
}]
}],
"caption": "",
"id": "",
"scope_name": "x_dnf_table"
}
Notice the first "section" has a caption, but ServiceNow treats the split section as its own separate section with no caption at all.
I want to change the spModel directive to produce only containers with captions as their own tab and if a container does NOT have a caption, to append it to the previous container that does have a caption.
I don't think you can edit this function as this is hosted as a file on Servicenow. See https://hi.service-now.com/scripts/app.$sp/directive.spModel.js then just control-f for the getNestedFields.
Per this thread; https://community.servicenow.com/thread/247907#1059129 I believe spModal is just a wrapper for $uibModal.
What you can do is make your own directive on sp_angular_provider.

empty array in angular-schema-form

I'm using angular-schema-form in my project and trying to add an empty array in my model.
I expected that array type schema form will not contain any items but it actually pushed one object in my array and showed it in from.
How can I init form with no items in array?
html
<div ng-app="app" ng-controller="Controller as ctr">
<form sf-schema="ctr.schema" sf-form="ctr.form" sf-model="ctr.model"></form>
{{ctr.model.comments}} - Where this object come from? This array was empty. Is it possible to keep it empty on load?
</div>
js
var myApp = angular.module('app', ['schemaForm'])
.controller("Controller", function() {
this.schema = {
"type": "object",
"title": "Comment",
"properties": {
"comments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"title": "Name",
"type": "string"
},
"comment": {
"title": "Comment",
"type": "string",
"maxLength": 20,
"validationMessage": "Don't be greedy!"
}
}
}
}
}
};
this.form = [{
"key": "comments",
"items": [
"comments[]"
]
}];
this.model = {
comments: [] // Empty array defined
};
});
Jsfiddle
The value you are looking for is startEmpty: true this will avoid pre-populating the array with an object.
Angular Schema Form: Array Documentation
The pre-population is defaulted to ensure that the form fields within an array are available when the form loads. The startEmpty: true value can override this behaviour.

Add optgroups to angular-selectize asynchronously

I am using angular-selectize directive in my project. For this, I need to load optgroups asynchronously. So far I have tried multiple approaches but none of them works. The problem is, you cannot use the data returned by a promise synchronously. On the flip side, I have also been unable to initialize selectize from inside a promise callback. Given below is the code I currently have. Note that it is only to be used to get the idea of the data I'm playing with, not to present it as something you can consider right.
app.js
$http
.get('/get-categories')
.then(getCategoriesSCB, getCategoriesFCB);
function getCategoriesSCB(response) {
if(typeof(response.data) === 'object') {
posControl.menuCategories = response.data[0];
posControl.menuCategoryGroups = response.data[1];
}
else {
getCategoriesFCB(response);
}
}
function getCategoriesFCB(response) {
console.log(response);
}
posControl.menuConfig = {
valueField: 'id',
labelField: 'title',
placeholder: 'Select Category',
optgroupField: 'class',
optgroupLabelField: 'label',
optgroupValueField: 'value',
optgroups: posControl.menuCategoryGroups,
maxItems: 1,
searchField: ['title', 'category'],
onInitialize: function(selectize) {
console.log('selectize is here');
},
}
index.html
<selectize config="POSCtrl.menuConfig" options="POSCtrl.menuCategories" ng-model="POSCtrl.menuModel"></selectize>
data returned by ajax call
[
// this array has to be used for options.
[{
"class": "57b83830babb9",
"category": "Food Menu",
"id": "57b83855b23f9",
"title": "Beverages"
}, {
"class": "57b83830babb9",
"category": "Food Menu",
"id": "57b83855c05de",
"title": "Cuisines"
}, {
"class": "57b83830babb9",
"category": "Food Menu",
"id": "57b83855cdcb4",
"title": "Steaks"
}, {
"class": "57b83830d0899",
"category": "Wholesale Coffee",
"id": "57b83830d0899",
"title": "Wholesale Coffee"
}],
// this array has to be used for optgroups
[{
"value": "57b83830babb9",
"label": "Food Menu"
}, {
"value": "57b83830d0899",
"label": "Wholesale Coffee"
}]
]
You should be able to load a selectize asynchronously by setting the values directly on the posControl.menuConfig:
function getCategoriesSCB(response) {
if (typeof(response.data) === 'object') {
posControl.menuConfig.options = response.data[0];
posControl.menuConfig.optgroups = response.data[1];
}
}

AngularJS ng-repeat only for Items with a Specific Subfield

How can I get ng-repeat to only repeat items which contain subfields? I have a list of videos that updates based on language preference. I want to do something like ng-repeat="video in videos" only where ng-show="video.title[videoLanguage]" would make the element show. When I try using ng-show, it works somewhat but I have other code that works based on the length of the videos list (which updates since not all the videos are available in every single language).
Here's my code:
<ul ng-init="select=0" ng-style="{'margin-top': ((videoContainerHeight - (videos.length * 160)) / (videos.length - 1)) * select}">
<li ng-repeat="video in videos" ng-class="{'selected': select == $index}" ng-click="$parent.select=$index; changeNextPage(video.url);">
<div class="thumbnail"></div>
<div class="title">
<div class="title-cell">
<h2 ng-bind="video.title[videoLanguage]"></h2>
</div>
</div>
</li>
</ul>
Videos list object:
{
"id": "videos",
"url": "/videos",
"view": "views/videos.html",
"nextPage": "#/home",
"videos": [{
"url": "#/videos/extraction",
"thumbnail": "img/thumbnails/thumbnail.jpg",
"title": {
"english": "Short Title"
}
}, {
"url": "#/videos/extraction",
"thumbnail": "img/thumbnails/thumbnail.jpg",
"title": {
"english": "Longer Title Here",
"spanish": "Hi"
}
}, {
"url": "#/videos/extraction",
"thumbnail": "img/thumbnails/thumbnail.jpg",
"title": {
"english": "This is a Really Really Really Long Title",
"spanish": "Hi"
}
}, {
"url": "#/videos/extraction",
"thumbnail": "img/thumbnails/thumbnail.jpg",
"title": {
"english": "Short Title",
"spanish": "Hi"
}
}]
}
I'm looking to have ng-repeat generate a 4 item list when the language is set to english and a 3 item list when the language is set to Spanish.
I have created a fiddle , I think this is exactly what you want, ahve a look
https://jsbin.com/dinuku/edit?html,js,output
I created a filter to filter items based on language
app.filter('languageFilter', function() {
return function(array, lang) {
return (array || []).filter(function(item) {
if (lang in item.title) {
return true;
}
return false;
});
};
});
I suggested you the ng-switch
ng-switch doc

Resources