Unable to display values from dynamic array, ionic 2 - arrays

I have defined array like this
addressData: Array<
{
title: any, city: any,country: any,
locality1: any,locality2: any,state: any,
street:any, zip_code:any,icon: any,
showDetails: boolean
}> = [];
Now i push the values of array like this
this.addressData.push
({
title: 'Address',
city:this.mapDetails.address[0].city,
country:this.mapDetails.address[0].country,
locality1:this.mapDetails.address[0].locality1,
locality2:this.mapDetails.address[0].locality2,
state:this.mapDetails.address[0].state,
street:this.mapDetails.address[0].street,
zip_code:this.mapDetails.address[0].zip_code,
icon: 'ios-add-circle-outline',
showDetails: false
});
mapDetails - contains array object , with object name as address and which is at index 0, hence i am using "this.mapDetails.address[0]" to access values.
In HTML i am using ngFOr to iterate values like this
<ion-item padding *ngFor="let d of addressData" (click)="toggleDetails(d)"><ion-icon color="primary" item-right [name]="d.icon"></ion-icon>
{{d.title}}
<div *ngIf="d.showDetails">
{{d.street}}<br/>
{{d.locality2}}<br/>
{{d.city}} - {{d.zip_code}}<br/>
{{d.state}} - {{d.country}}<br/>
</div>
</ion-item>
The issue is, the error which I am getting is
"ModalCmp ionViewPreLoad error: Cannot read property 'address' of undefined"
Help me out with this error please.

Related

Cannot find a differ supporting object '[object Object]' of type 'object'. - context menu issues

I have issues with context menu. I am not sure why, I made similar thing many times but now I am unable to pass it. When I deleted this line:
<div *ngFor="let element of contextMenu">
</div>
Context menu works fine (but I need this line to fill my context menu.
This is part of html:
<mat-menu #contextMenu="matMenu">
<ng-template matMenuContent>
<div *ngFor="let element of contextMenu">
</div>
</ng-template>
</mat-menu>
And my context menu object:
#Input() contextMenu: MenuElement[];
And html with filled input:
<lib-mp-file-explorer
[fileElements]="fileElements | async"
[path]="currentPath"
[canNavigateUp]="canNavigateUp"
[topMenu]="topMenu"
[contextMenu]="contextMenu"
(folderAdded)="addFolder($event)"
(elementRemoved)="removeElement($event)"
(navigatedDown)="navigateToFolder($event)"
(navigatedUp)="navigateUp()"
(elementRenamed)="renameElement($event)"
(elementMoved)="moveElement($event)"
>
</lib-mp-file-explorer>
And my construction:
this.contextMenu = [
{
name: 'Open in Mark',
icon: 'M',
action: undefined,
disabled: true
},
...
]
I hate this error now:
core.js:5828 ERROR Error: Cannot find a differ supporting object
'[object Object]' of type 'object'. NgFor only supports binding to
Iterables such as Arrays.
But my array is iterable T.T
Your menu reference variable has the same name..
<mat-menu #contextMenu="matMenu">
..as the array you are trying to loop through
<div *ngFor="let element of contextMenu">
A template reference variable is not iterable.
Try renaming your array:
<div *ngFor="let element of menuElements">
And Input():
#Input() menuElements: MenuElement[];
and then
this.menuElements = [
// your data
]
You can check what there are actual values in your contextMenu:
<p>contextMenu {{ contextMenu | json }}
However, your error says that it is object, so you can use keyvalue pipe since Angular 6:
<div *ngFor="let item of contextMenu | keyvalue">
Key: <b>{{item.key}}</b> and Value: <b>{{item.value}}</b>
</div>

Render last element of nested array of Object in Angular HTML template

I have an Object named comment, which has description property and editedDescription Array. Whenever user edits description, new description will be pushed into editedDescription array.This array is used so as to maintain history of edited descriptions.
Following is my comment Object :
export interface Comment {
userName: String,
userImage: String,
description: String,
upvote : Number,
downvote : Number,
createdDate: Date,
replies: [
{
userName: String,
userImage: String,
description: String,
upvote : Number,
downvote : Number,
createdDate: Date
}
],
editedDescription: [
{
Description: String,
editedDate: Date
}
]
}
In order to output last element of editedDescription array, I have tried :
{{ comment?.editedDescription[editedDescription?.length-1]?.Description}}
I am getting following error - 'Cannot read property '-1' of undefined '
I have made use of safe navigation operator to check if array exists but im getting cannot read -1 of undefined
this is my code where in part is failing
<div *ngIf="comment?.editedDescription?.length == 0 ; else edited_comment">
<p> {{ comment?.description }}</p>
</div>
<ng-template #edited_comment>
<p> {{ comment?.editedDescription[editedDescription?.length-1]?.Description}}</p>
</ng-template>
*ngIf conditions check if there is no data in editedDescription array, use description property else use last element of editedDescription array.
I think it needs to be the following, as at the moment you are not trying to access the array through comment where it sounds like it is stored.
{{ comment?.editedDescription[comment.editedDescription.length -1 ]?.Description}}
You still need to access comment when looking for the length. Put the safety operators back in when you are happy it is working. Below shows a simplified example of what you have tried.
const obj = { hello: [1, 2, 3] };
console.log(obj.hello[obj.hello.length - 1]); // last element, expected 3
// console.log(obj.hello[hello.length - 1]) // This is like what you have done.

How to display value of object sent by node

I have question i try to put value from nodejs by init() in angularjs, later i put to $scope.product and when i try display i have problem with:
node:
return res.render('product/product', { title: 'Express', product: products });
angular:
<body ng-controller="productsController" ng-init="productView('<%= product %>')">
<% include ../share/header.ejs %>
{{ product.title }}
{{ product.price }}
</body>
controller:
$scope.productView = function (product) {
$scope.product = JSON.parse(product);
console.log(product);
};
Error: [$parse:syntax] Syntax Error: Token 'bf' is unexpected, expecting [)] at column 55 of the expression [productView('{ _id: 5950c8902a76e81b5cc56a6f, title: 'bf', price: 7, __v: 0 }')] starting at [bf', price: 7, __v: 0 }')].
product: products - it's possible you are passing down an array of objects instead of an individual one. If that's the case, either change the res.render call on the server to pass only 1 product, or change the client-side code to expect an array and use something like ngRepeat to iterate over them.
you dont need productView function, try simply
<body ng-controller="productsController" ng-init="product='<%= product %>'">
{{ product.title }}
{{ product.price }}

Angular - Filtering an ng-repeat by Item.User._id

Im trying to filter an ng-repeat by an id value.
$scope.filter = $stateParams.id; --> 56a1832a36dc3d0e00c7aa3f
Heres the model for the Item Object with relevant vlues
var ItemSchema = new Schema({
title: {
type: String,
maxlength: 150
}
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
How exactly do i filter the Items by the user._id ?
My attempt which is giving no results.
<div ng-repeat="saving in savings| filter: {user : 'filter'}">
https://plnkr.co/edit/sihBuRe9vNKO0jB1Wk8b
The docs explain using filters very well. The filter filters the array by property you pass to it. If it's an object, it will match its properties against each item in the array. This means that item in array with property user: {_id: 2} will be shown.
<div ng-repeat="saving in savings | filter:{user: {_id: 2}}">{{saving.title}}</div>
You can checkout this question for another example.

angularJS - How to filter by one item in object only

In this JSFiddle (https://jsfiddle.net/eug0taf9/9/), I select a rating and expect an image to be displayed.
What is happening?
When I select rating 'High', 2 images show up instead of 1 because the filter is catching category 'High' and also description 'High' of an image in category 'Low'.
What do I expect to happen?
On selecting rating "High", I only want the category to be filtered. I don't need it to be filtered by description too.
Any suggestions on how to solve this?
HTML code:
<div ng-app="myApp" ng-controller="myCtrl">
<span>Select a rating</span>
<select ng-model="catselect"
ng-options="category for category in imageCategories"
ng-change="valueSelected(catselect)">
<option value>All</option>
</select>
<!--<p>Select <input ng-model="categories"/></p>-->
<ul class="photosmenu">
<li ng-repeat="image in images | filter : catselect" ng-click="setCurrentImage(image)">
<img ng-src="{{image.image}}" alt="{{image.stars}}" width="300px"/>
</li>
</ul><!-- End of List -->
</div>
Angular Code:
var mod = angular.module("myApp", []);
mod.controller("myCtrl", function($scope){
$scope.images = [
{category: 'High', image: 'img/1.png', description: 'Random Photo', stars: '4/5'},
{category: 'Medium', image: 'img/6.png', description: 'ApplePhoto', stars: '3/5'},
{category: 'Low', image: 'img/13.png', description: 'High Top Photo', stars: '2/5'},
{category: 'None', image: 'img/16.png', description: 'Kilt Photo', stars: '0/5'}];
$scope.currentImage = $scope.images[0];
$scope.imageCategories = ["High", "Medium", "Low", "None"];
$scope.valueSelected = function (value) {
if (value === null) {
$scope.catselect = undefined;
}
};
});
That is because you have a global match filter which will match on all properties, if you want to filter on specific property set your filter object accordingly. i.e
<li ng-repeat="image in images | filter :{category: catselect}"
Demo
or you could also set your ng-model to an object,
<select ng-model="catselect.category"
and do:
<li ng-repeat="image in images | filter :catselect"
Demo
Check out documentation:
string: The string is used for matching against the contents of the array. All strings or objects with string properties in array that match this string will be returned. This also applies to nested object properties. The predicate can be negated by prefixing the string with !.
Object: A pattern object can be used to filter specific properties on objects contained by array. For example {name:"M", phone:"1"} predicate will return an array of items which have property name containing "M" and property phone containing "1". A special property name $ can be used (as in {$:"text"}) to accept a match against any property of the object or its nested object properties. That's equivalent to the simple substring match with a string as described above. The predicate can be negated by prefixing the string with !. For example {name: "!M"} predicate will return an array of items which have property name not containing "M".

Resources