How to add multiple data objects using Array.fill in Angular - arrays

I am developing some code using Angular. In my ts file, I have created an array as below
ArrayB= [
{ id: 1, src: 'url' },
{ id: 2, src: 'url' },
{ id: 3, src: 'url' },
{ id: 4, src: 'url' },
{ id: 5, src: 'url' }];
This is ArrayA
ArrayA = Array(5).fill(' ').map((index,_)=>({id:index,src:url}));
I have created grid in HTML file. I want put images (in URL) on each grid tiles.
<mat-grid-list cols="10">
<mat-grid-tile *ngFor="let cell of ArrayA; let i = index">
<div
class="cell"
cdkDropList
[cdkDropListData]="cell"
(cdkDropListDropped)="drop($event)"
[style.background]="i == indexOver ? 'yellowgreen' : 'yellowgreen'"
(mouseover)="this.indexOver = i"
(mouseout)="indexOver = -1" >
<div cdkDrag>
<img
*ngIf="cell.src"
[src]="cell.src"
width="100%"/>
<span *ngIf="!cell.src"></span>
<div *cdkDragPlaceholder></div>
</div>
</div>
</mat-grid-tile>
</mat-grid-list>
So how can I put multiple data objects to ArrayA like ArrayB and assign images to each grid tile.

Related

Angular 2 - how to clean array in form

I need help.
I create app in Angular2(4) where I have Form with 2 select boxes and 1 checkbox. And I want to achieve dependence this boxes. For example I have this array:
dataJSON = [
{
productName: 'Product 1',
variants: [
{
variantName: 'Variant1',
variantType: [
'Type1', 'Type2', 'Type3'
]
},
{
variantName: 'Variant2',
variantType: [
'Type1', 'Type2', 'Type3'
]
},
{
variantName: 'Variant3',
variantType: [
'Type1', 'Type2', 'Type3'
]
},
]
},
{
productName: 'Product 2',
variants: [
{
variantName: 'Variant1',
variantType: [
'Type1', 'Type2', 'Type3', 'Type4'
]
},
{
variantName: 'Variant2',
variantType: [
'Type1', 'Type2', 'Type3'
]
}
]
},
{
productName: 'Product 3',
variants: [
{
variantName: 'Variant1',
variantType: [
'Type1', 'Type2', 'Type3'
]
},
{
variantName: 'Variant2',
variantType: [
'Type1', 'Type2', 'Type3'
]
},
{
variantName: 'Variant3',
variantType: [
'Type1', 'Type2', 'Type3'
]
},
{
variantName: 'Variant4',
variantType: [
'Type1', 'Type2', 'Type3', 'Type4'
]
}
]
}
];
So when I in first select box choose 'Product 1' then in second select box I will have options: 'Variant1', 'Variant2', 'Variant3'. Then when I choose 'Variant1' I will have in checkboxes options: 'Type1', 'Type2', 'Type3'.
When I choose everithing I want save what and base on that make request to API for data.
What I have now.
<form [formGroup]="productForm" (ngSubmit)="submitForm()">
<div class="form-group row">
<div class="col-md-4 col-sm-4 col-lg-4">
<label>Product</label>
<select formControlName="productName" (change)="productChanged()" class="form-control">
<option >Pick a Product...</option>
<option *ngFor="let l of dataJSON">{{l.productName}}</option>
</select>
</div>
<label>Variant</label>
<div class="col-md-4 col-sm-4 col-lg-4">
<select formControlName="variants" (change)="variantsChanged()" class="form-control">
<ng-template ngFor let-variant [ngForOf]="(variantAfterChangeEvent)">
<option>Pick a variant...</option>
<option *ngFor="let v of variant.variants">{{v.variantName}}</option>
</ng-template>
</select>
</div>
<div class="col-md-4 col-sm-4 col-lg-4">
<label>Type</label>
<ng-template ngFor let-type [ngForOf]="(typeAfterChangeEvent)">
<div *ngFor="let t of type[0].variantType">
<input type="checkbox" class="minimal" (change)="onChange(t, $event.target.checked)"> {{t}}
</div>
</ng-template>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
variantAfterChangeEvent: any[];
typeAfterChangeEvent: any[];
productForm: any;
constructor(private fb: FormBuilder) {
this.productForm = fb.group({
productName: [],
variants: [],
type: this.fb.array([])
});
}
productChanged() {
const productName = this.productForm.get('productName').value;
this.variantAfterChangeEvent = this.dataJSON.filter(s = > s.productName);
}
variantsChanged() {
const variants = this.productForm.get('variants').value;
this.typeAfterChangeEvent = this.variantAfterChangeEvent
.filter((element) =>
element.variants.some((subElement) => subElement.variantName === variants))
.map(element => {
const newElt = Object.assign({}, element ); // copies element
return newElt.variants.filter(subElement => subElement.variantName === variants);
});
}
onChange(type: string, isChecked: boolean) {
const typeFromArray = <FormArray>this.productForm.controls.type;
if (isChecked) {
typeFromArray.push(new FormControl(type));
} else {
const index = typeFromArray.controls.findIndex(x => x.value === type)
typeFromArray.removeAt(index);
}
console.log('onChange() ' + JSON.stringify(this.productForm.value));
}
submitForm() {
console.log('submitForm ' + JSON.stringify(this.productForm.value));
}
But now when I choose Product -> Variant -> Type and than before Submit I want change Product and choose something else different Product -> Variant -> Type and then Submit I get what I choose as last but in 'type' I have also what I choose first time. So how can I clean 'type' array in productForm when I change somenting in Form = Product or Variant.
And also how can I disable Submit Form Button when not all items(boxes) are selected?
EDIT:
Plnkr
It would be better if you could create a plunker.
Based on what I understood, you can get ngModel from each control and clear other control's value on change.
To disable the form until all values are selected, add required property in each control and add [disabled]="!productForm.valid" in submit button

Google chart in angularjs ng-repeat

I am new to AngularJs and Google charts. My requirement is to show Google charts dynamically in ng-repeat for each li.
<li ng-repeat="ques in surveyquestions">
<label for="{{ques['questions']}}">
{{ques['id']}} {{ques['questions']}}
</label>
<div ng-init="calltry(ques['option_array'],ques['id'])"></div>
<div id="chartdiv{{ques['id']}}"></div>
</li>
In above code through ng-init I pass the data to render the Google chart. In JavaScript I used as below but it's not working.
var chart = new google.visualization.ColumnChart(document.getElementById('chartdiv'+id));
It's working fine when id is static like below.
<div id="chartdiv"></div>
var chart = new google.visualization.ColumnChart(document.getElementById('chartdiv'));
Please help to sort out what is the issue.
Try with angular-google-chart,
Refer :https://angular-google-chart.github.io/angular-google-chart/docs/latest/examples/bar/
<div class="chartContainer" ng-repeat="data in arrayDiv">
<div layout-padding layout-margin google-chart chart="drawChart(data)">
</div>
</div>
$scope.drawChart = function (value) {
$scope.chartData = [];
var chartValue = {
c: [{
v: 'subject
}, {
v: 5,
f: " questions"
}, {
v: 6,
f: " questions"
}]
};
$scope.chartData.push(chartValue);
$scope.qaChart = {};
$scope.qaChart.type = "BarChart";
$scope.qaChart.data = {
"cols": [{
id: "Sections",
label: "Subject",
type: "string"
}, {
id: "Correct",
label: "Correct",
type: "number"
}, {
id: "Wrong",
label: "Wrong",
type: "number"
}],
"rows": $scope.chartData
};
$scope.qaChart.options = {
"isStacked": "true",
"fill": 20,
"displayExactValues": true,
"colors": ['#4CAF50', '#EF5350', '#00adee'],
"vAxis": {
"title": " Questions",
},
"hAxis": {
"title": "Details",
}
};
return $scope.qaChart;
};

Adding conditional value to angular ng-table

I want to add glyphicon to a column based on row value in ng-table component .For example if row.firstProperty==row.secondProperty then the glyph be added to column.I know how to do this in angular Grid UI but although I review documentations and examples but ‍‍‍‍‍‍I did not find any way in ng-Table.Can anyone suggest a solution to my issue?
Edit:My scenario is that I have a custom directive that it is used to produce many pages with same style and functionality by getting page data and in part of it ng-table is used by defining template for my directive.
ng-table.html
<table ng-table="to.tableParams" class="table" show-filter="{{::to.showFilter}}">
<tr ng-show="to.showHeaders">
<th class="th-select" ng-repeat="column in to.columns">{{column.title}}</th>
</tr>
<tr ng-repeat="row in $data">
<td ng-repeat="column in to.columns" ng-show="column.visible" sortable="column.field" ng-click="save(row)">
{{row[column.field][column.subfield] || row[column.field]}}
<span compile="column.getValue()" ></span>
</td>
</tr>
ngTable Columns is defined in Controllers and one of the columns is html values like glyphicons and buttons that is maked base on object named actionList which is defined in each controller like below:
vm.actionList = [
{
name: 'edit',
body: function (row) {
$state.go("editrule", {ruleId: row.id});
},
glyph: 'glyphicon-pencil',
permission: $scope.permission.edit,
showCondition:"true"
},
{
name: 'view',
body: function (row) {
$state.go("showrule", {ruleId: row.id});
},
glyph: "glyphicon-eye-open",
permission: $scope.permission.watch,
showCondition:"row.modifiedDate==row.createDate"
},
{
name: 'history',
body: function (row) {
$state.go("rulehistory", {ruleId: row.id});
},
glyph: "glyphicon-info-sign",
showCondition: "row.modifiedDate!=row.createDate",
permission: $scope.permission.history
}
];
.I put the logic for creating html column to my directive to prevent repeated code from controllers and delivering it to controllers and the controller part for defining columns is as below :
vm.columns = [
{
title: $translate.instant('URL'),
translate: "URL",
field: 'url',
visible: true,
alignment: 'text-align-lg-left'
},
{
title: $translate.instant('MATCH_TYPE'),
translate: "MATCH_TYPE",
field: 'matchType',
visible: true,
alignment: 'text-align-lg-center',
filter: [{lowercase: []}]
},
{title: $translate.instant('PRIORITY'), translate: "PRIORITY", field: 'priority', visible: true,alignment: 'text-align-lg-center'},
{title: $translate.instant('SOURCE'), tanslate: "SOURCE", field: 'source', visible: true,alignment: 'text-align-lg-center'},
{title: $translate.instant('CATEGORY'), translate: "CATEGORY", field: 'category', visible: true,alignment: 'text-align-lg-center'},
{
title: $translate.instant('CREATE_DATE'),
translate: "CREATE_DATE",
field: 'createdDate',
visible: true,
alignment: 'text-align-lg-center'
},
{
title: $translate.instant('LAST_CHANGE'),
translate: "LAST_CHANGE",
field: 'modifiedDate',
visible: true,
alignment: 'text-align-lg-center'
},
{title: $translate.instant('ACTION') ,translate: "ACTION", field: 'action', visible: true,alignment: 'text-align-lg-center'},
{title: '', visible: true, getValue: htmlValue, id: "actionList"}/*actions*/
];
function htmlValue() {
return $sce.trustAsHtml(actions);
}
The action value comes from directive that contains htmls.The Directive part is as below :
scope.html = function htmlValue() {
var html = "";
/*intentionaly angular ng-repeat not used*/
for (var i = 0; i < scope.actionList.length; i++) {
scope.entry = scope.actionList[i];
scope.permission = scope.entry.permission;
scope.myglyph = scope.entry.glyph;
if (typeof scope.entry.permission == 'undefined' || scope.entry.permission == true) {
debugger
html = '<button ng-show="{{entry.condition}}" type="button" class="btn btn-list" ng-click=' + $interpolate("{{entry.name}}(row)")(scope) + '> ' +
'<span class=\"glyphicon ' + $interpolate("{{entry.glyph}}")(scope) + '\"></span>' +
'</button>' + html;
console.log("this is test");
console.log(scope.test);
}
}
}
scope.$watch('refreshDataFilter', function (newValue, oldValue) {
/*EXTRACT ACTIONS*/
for (var i = 0; i < scope.actionList.length; i++) {
var entry = scope.actionList[i];
Object.defineProperty(scope, entry.name, {value: entry.body});
Object.defineProperty(scope, entry.showCondition, {value: "aaa"});
}
/*define table data filler*/
if (newValue == true) {
renderTable();
scope.refreshDataFilter = false;
}
});
The main problem is here that if I interpolate the values of entry.showCondition I always get the value of of last item in actionList. Is there any solution that I can make html part of table base on conditions?

I'm trying to include ng-swicth inside ng-repeat loop

I have a menu to navigate through my data model:
<div class="nav">
<span us-spinner ng-if="vm.dataReady == false"></span>
<ul class="nav">
<li ng-repeat="section in vm.data"
ng-class="{'active':vm.activePersonalDataTab == $index}"
ng-click="vm.personalDataTabClick($index)">
{{section.name}}
</li>
</ul>
</div>
Data is a simple object like this one:
personalData: [
{ name: "Общие сведения", src: "CommonInfo/GetCommonInfo", dataType: 0, data: null },
{ name: "Биография", src: null, subNames: [
{ name: "Сведения об образовании", src: "EducationInfo/Read", dataType: 1, data: null },
{ name: "Сведения о службе в вооруженных силах", src: "MilitaryServiceInfo/Read", dataType: 1, data: null },
{ name: "Сведения о семейном положении", src: "FamilyInfo/Read", dataType: 1, data: null },
{ name: "Сведения о судимости", src: "ConvictionInfo/Read", dataType: 1, data: null }
]},
{ name: "Занимаемые должности", src: "PersonPosition/Read", dataType: 1, data: null },
{ name: "Поощрения и взыскания", src: "PromotionRecovery/Read", dataType: 1, data: null },
{ name: "Публикации в СМИ", src: "PublicationInfo/Read", dataType: 1, data: null },
{ name: "Сведения о смерти", src: "DeathInfo/GetDeathInfo", dataType: 0, data: null }
], //dataType: 0 - list, 1 - table
Where 'src' is a name of API controllers. My service using them to get data and then write it in the 'data' property. Now I'm trying to use ng-repeat to loop through all data items and ng-switch to check if it'a one that is selected in my menu (selected menu index is stored in vm.activePersonalDataTab):
<div ng-repeat="section in vm.data" ng-init="sectionIndex=$index" ng-switch="vm.activePersonalDataTab">
<div ng-switch-when="{{sectionIndex}}" ng-switch="vm.data[sectionIndex].dataType">
<div ng-switch-when="0" class="info">
<ul>
<li ng-repeat="item in vm.dict[sectionIndex]" class="{{vm.getLiClass($index)}}"
ng-init="field = vm.getFieldValue(sectionIndex,$index)">
<div class="my-label">{{vm.getFieldName(sectionIndex,$index)}} </div>
<div class="my-info">{{field.type === 1 ? (field.value | date:'dd.MM.yyyy') : field.value}} </div>
</li>
</ul>
</div><!--Если данные представлены простым списком-->
<div ng-switch-when="1" class="table"></div>not yeat<!--Если данные представлены таблицей-->
<div ng-switch-default class="bunch">not yeat</div><!--Если данные представлены набором таблиц-->
</div>
It's works if I change {{sectionIndex}} to 0 in ng-switch-when="{{sectionIndex}}. Byt I whant to use index from ng-repeat for automate this part of my code.

How do you show ng-repeated children of filtered array?

I have a drop-down filtered array, but the array I'd like to use is a little more complex, with nested data, similar to this http://jsfiddle.net/vojtajina/u75us/
I'd like to combine both ideas, but can't figure out why my fiddle doesn't display the 'child nodes'
<div class="col-md-12" ng-controller="App04Ctrl">
<p>Search:
Filter:
<select ng-model="filterItem.store" ng-options="item.name for item in filterOptions.stores">
</select>
Sort:
<select ng-model="sortItem.store" ng-options="item.name for item in sortOptions.stores">
</select>
</p>
<ul>
<li ng-repeat="item in locations | orderBy:'price':reverse | filter:customFilter" >Name: {{item.name}} Price: {{item.price}} Location: {{item.location}}</li>
<ul>
<li ng-repeat="package in location.packages">{{package.name}} has services:
<ul>
<li ng-repeat="service in package.services">{{service.name}}</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
angular.js:
var app = angular.module('app04', []);
function App04Ctrl($scope) {
//Contains the filter options
$scope.filterOptions = {
stores: [
{id : 2, name : 'Show All', location: 'All Locations' },
{id : 3, name : 'Ashburn', location: 'Ashburn' },
{id : 4, name : 'San Francisco', location: 'San Francisco' },
{id : 5, name : 'Denver', location: 'Denver' },
{id : 6, name : 'Chicago', location: 'Chicago' },
{id : 7, name : 'Irvine', location: 'Irvine' }
]
};
//Contains the sorting options
$scope.sortOptions = {
stores: [
{id : 1, name : 'Price Highest to Lowest' },
{id : 2, name : 'Price Lowest to Highest' },
]
};
//Mapped to the model to filter
$scope.filterItem = {
store: $scope.filterOptions.stores[0]
}
//Mapped to the model to sort
$scope.sortItem = {
store: $scope.sortOptions.stores[0]
};
//Watch the sorting model - when it changes, change the
//ordering of the sort (descending / ascending)
$scope.$watch('sortItem', function () {
console.log($scope.sortItem);
if ($scope.sortItem.store.id === 1) {
$scope.reverse = true;
} else {
$scope.reverse = false;
}
}, true);
//Custom filter - filter based on the location selected
$scope.customFilter = function (locations) {
if (locations.location === $scope.filterItem.store.location) {
return true;
} else if ($scope.filterItem.store.location === 'All Locations') {
return true;
} else {
return false;
}
};
// Location data
$scope.locations = [{
name: "product1",
price: 198,
location: 'Ashburn',
packages: [{
name: 'Doom Patrol',
services: [{
name: 'Mento'}, {
name: 'Vox'}, {
name: 'Robotman'}]}, {
name: 'Suicide Squad',
services: [{
name: 'King Shark'}]}, {
name: 'Shadowpact',
services: [{
name: 'Zauriel'}, {
name: 'Enchantress'}, {
name: 'Ragman'}, {
name: 'Nightshade'}]}]}, {
name: "product2",
price: 402,
location: 'Chicago',
packages: [{
name: 'Metal Men'}, {
name: 'Legion of Superheroes',
services: [{
name: 'Ultra Boy'}, {
name: 'Kid Quantum'}]}]}, {
name: "product2",
price: 300,
location: 'Denver',
packages: [{
name: 'Freedom Fighters',
services: [{
name: 'Damage'}, {
name: 'Iron Munro'}]}, {
name: 'Birds of Prey',
services: [{
name: 'Huntress'}, {
name: 'Black Alice'}]}]}, {
name: "product2",
price: 1243,
location: 'Irvine',
packages: [{
name: 'The Outsiders'}, {
name: 'Zoo Crew',
services: [{
name: 'Rubberduck'}, {
name: 'Captain Carrot'}]}, {
name: 'The Elite',
services: [{
name: 'Vera Black'}, {
name: 'Manchester Black'}]}, {
name: 'Justice Legion Alpha'}]}
];
}
http://jsfiddle.net/jdacio/Vfx3y/2/
What am I missing? Am I on the right track? is there a better way to do this?
There are two problems that I see in your code above:
[1] Notice that you have closed the <li> tag, thus stopping the nesting of your ng-repeat directive to show the packages and and services of each item location. Simply remove the </li> closing tag and that should solve your first problem.
<li ng-repeat="item in locations | orderBy:'price':reverse | filter:customFilter" >
Name: {{item.name}}
Price: {{item.price}}
Location: {{item.location}}
</li> <!-- THIS IS THE PROBLEM!! -->
[2] As what Mosho mentioned, your nested ng-repeat directive is using a location reference which does not exist in the current context of its parent ng-repeat directive. The simplest solution would be to change
<li ng-repeat="package in location.packages">
to
<li ng-repeat="package in item.packages">
The resulting HTML code should be:
<ul>
<li ng-repeat="item in locations | orderBy:'price':reverse | filter:customFilter" >
Name: {{item.name}}
Price: {{item.price}}
Location: {{item.location}}
<ul>
<li ng-repeat="package in location.packages">{{package.name}} has services:
<ul>
<li ng-repeat="service in package.services">{{service.name}}</li>
</ul>
</li>
</ul>
</li>
</ul>
Instead of location.packages, it should be item.packages. (or 'location in locations' rather than 'item in locations').
<li ng-repeat="item in locations | orderBy:'price':reverse | filter:customFilter">
...
<li ng-repeat="package in location.packages">
You refer to location, but you declare item in locations.

Resources