error TS2339: Property 'title' does not exist on type 'string' - angular11

What can I do now please help me out....TIA
**component.html`
<mat-accordion multi="true" *ngIf="posts.length > 0">
<mat-expansion-panel *ngFor="let post of posts">
<mat-expansion-panel-header>
{{ post.title }}
</mat-expansion-panel-header>
<p>{{ post.content }}</p>
</mat-expansion-panel>
</mat-accordion>
<p class="text-info-mat-body-1" *ngIf="posts.length ==0">No post added yet!</p>`**
{{post.title}},{{post.content}} "error TS2339: Property 'content' does not exist on type 'string'."
**component.ts`
export class PostListComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
#Input() posts:string[]=[];
}
`**

Related

VueJS 3 Composition API. Can anyone explain why this will not work?

I'm loading a simple JSON file, assigning it to a reactive variable, and displaying it in the template. However, it only works partly.
{{ people }}, {{ people.People }}, and in a people.People in a v-for loop work as expected,
but accessing the people.People[0].FullName fails. But why? Any insight is appreciated.
Here is my .json
{
"People": [
{
"FullName": "The Json"
}, {
"FullName": "The Jetsons"
}
]
}
And here is the component.vue code
<template>
<h1>Test</h1>
<div>
<p>{{ people }}</p> <!-- Works and displays: { "People": [ { "FullName": "The Json" }, { "FullName": "The Jetsons" } ] } -->
<p>{{ people.People }}</p> <!-- Works and displays: [ { "FullName": "The Json" }, { "FullName": "The Jetsons" } ] -->
<p>{{ people.People[0].FullName }}</p> FAILS - Uncaught TypeError: $setup.people.People is undefined
<p v-for="(item, idx) in people.People" :key="idx">
{{ item.FullName }} <!-- Works as expected -->
</p>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
name: "Test",
setup() {
const people = ref({});
fetch('http://localhost:3000/data/people.json')
.then(response => response.json())
.then(data => people.value = data);
return {
people
}
}
}
</script>
<style>
</style>```
Thanks
At "setup time" before your json is loaded :
people = {}, so people.People[Ø] raises an error cause people.People is not defined at this moment
In your exemple
{{ people }} and {{ people.People }} display something cause it's reactive and you just don't have time to see it before the json is loaded
There is several ways to manage this. ere is two of them
Add an if
<p v-if="people.People">{{ people.People[0].FullName }}</p>
Init with default walues
const people = ref({
People: []
});

How should I be referencing firebase data in Vue component?

I can see the data in the Vue console but I'm getting an error in the console: 'Property or method "rsvp" is not defined on the instance but referenced during render.'
How should I be referencing the firebase data?
<template>
<ul>
<li
v-for="(data, index) in rsvp"
:key="index"
>
<div
v-for="(name, index) in data.name"
:key="index"
>
{{ name }}
</div>
<div v-if="data.dietRestrictions">
Diet Restrictions: {{ data.dietRestrictions }}
</div>
</li>
</ul>
</template>
<script>
import { db } from "../../config/db";
export default {
name: "Results",
firebase: {
rsvp: db.ref("rsvp"),
},
}
</script>
I just forgot to declare rsvp in data().
data() {
return {
rsvp: {},
}
},

ngClass doesn't refresh css class

I have great fight with angular 4. I wan`t to make simple star rating component. My template looks like this :
<div class="card rating">
<div class="card-section">
<p class="ratings-card-header">{{name}}</p>
<div class="grid-x grid-margin-x">
<div class="rating-block cell small-12 medium-6 large-3"
*ngFor="let ratingItem of values; let ratingItemIndex = index">
<p class="ratings-type">{{ ratingItem.label }}</p>
<div class="rating-block-rating">
<a *ngFor="let a of getFakeArrayIteration(); let index = index" [ngClass]="time"
(click)="changeValue(ratingItem, index + 1)" >
<i [ngClass]="isStarSelected(index, ratingItem)">
</i>
</a>
</div>
</div>
</div>
</div>
And my controller class look like this:
import {Component, Input, OnInit} from '#angular/core';
import 'foundation-sites';
import {LabelledValue} from './star-rating-vaules';
#Component({
selector: 'star-rating',
templateUrl: './star-rating.component.html',
styleUrls: ['./star-rating.component.scss']
})
export class StarRatingComponent implements OnInit {
#Input() public name: string;
#Input() public maxValue: number;
#Input() public values: LabelledValue[];
private time: Date;
constructor() {
}
ngOnInit() {
console.log(this.values);
}
changeValue(item: LabelledValue, newValue: number) {
item.value = newValue;
this.time = new Date();
}
isStarSelected(index: number, item: LabelledValue): string {
if (index < item.value) {
return 'fas fa-2x fa-minus-square';
} else {
return 'far fa-2x fa-star';
}
}
getFakeArrayIteration(): any[] {
return new Array(this.maxValue);
}
}
export class LabelledValue {
public key: string;
public label: string;
public value: number;
}
Works on beginning. Set proper amount of stars. But if value changes, you cannot set less stars than initial value. I have no clue what`s wrong
Problem is caused because on first adding icon it is translated somehow to svg. After changes of state it is not a problem, but on beginning is unfortunately blocker of css change. Also I created new question: Prevent svg translation of fontawesome

How can i get the first hero to be selected as an initial condition in angular2?

In angular2 heros tutorial
template: `
<h1>{{title}}</h1>
<h2>My Heroes</h2>
<ul class="heroes">
<li *ngFor="let hero of heroes"
[class.selected]="hero === selectedHero"
(click)="onSelect(hero)">
<div *ngIf="hero ==heroes[0]"> first hero </div>
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
<hero-detail [hero]="selectedHero"></hero-detail>`
export class AppComponent implements OnInit {
title = 'Tour of Heroes';
heroes: Hero[];
selectedHero: Hero;
constructor(private heroService: HeroService) { }
getHeroes(): void {
this.heroService.getHeroes().then(heroes => this.heroes = heroes);
}
ngOnInit(): void {
this.getHeroes();
}
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
}
How do I make the first hero item selected when it first starts
and i want to change selectedHero when i click another hero item
this.heroService.getHeroes().then(heroes => {
this.heroes = heroes;
this.selectedHero = this.heroes[0];
});

Angular 2, How console the object object or loop through object object

I am pulling the api from http://ecommerce-ux.london/wp-json/wp-api-menus/v2/menus/2 and it seem to have everything setup correctly and now would like to display from the api object.items ( that is the menu children)
When I do {{ menus }} I get [object object].
Apparently you can not use *ngFor if it is an object, so I needed to creat a pipe but still can figure out how to display the elements as all I get Keys or values.
Could someone please tell me where I gone wrong.
main-menu.component.html
<ul>
<li *ngFor="let menu of menus | menu">
{{ menu.key }} {{ menu.value }}
<ul>
<li *ngFor="let items of menu | menu">
{{ items.key }}
</li>
</ul>
</li>
</ul>
menu.service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { Menu } from './menu';
#Injectable()
export class MenuService {
private _wpMenuBase = "http://ecommerce-ux.london/wp-json/wp-api-menus/v2/";
constructor(private http: Http) { }
getPosts(): Observable<Menu[]> {
return this.http
.get(this._wpMenuBase + 'menus/2')
.map((res: Response) => res.json());
}
}
main-menu.components.ts
import { Component, OnInit } from '#angular/core';
import { Menu } from '../menu';
import { MenuService } from '../menu.service';
import { Router, ActivatedRoute, Params } from '#angular/router';
#Component({
selector: 'app-main-menu',
templateUrl: './main-menu.component.html',
styleUrls: ['./main-menu.component.css'],
providers: [MenuService]
})
export class MainMenuComponent implements OnInit {
menus: Menu[];
constructor( private menuService: MenuService, private router: Router ) { }
getPosts(){
this.menuService
.getPosts()
.subscribe(res => {
this.menus = res;
});
}
ngOnInit() {
this.getPosts();
}
}
menu.ts
export class Menu {
}
JSON
{
"ID":2,
"name":"Main menu","slug":"main-menu",
"description":"","count":2,
"items":[
{
"id":4,"order":1,"parent":0,
"title":"Sample Page","url":"http:\/\/ecommerce-ux.london\/sample-page\/","attr":"","target":"","classes":"","xfn":"","description":"","object_id":2,"object":"page",
"object_slug":"sample-page",
"type":"post_type",
"type_label":"Page"},
{
"id":7,
"order":2,
"parent":0,"title":"other page","url":"http:\/\/ecommerce-ux.london\/other-page\/","attr":"",
"target":"","classes":"","xfn":"",
"description":"",
"object_id":5,"object":"page","object_slug":"other-page","type":"post_type","type_label":"Page"}
],
"meta":
{
"links":
{
"collection":"http:\/\/ecommerce-ux.london\/wp-json\/wp\/v2\/menus\/",
"self":"http:\/\/ecommerce-ux.london\/wp-json\/wp\/v2\/menus\/2"
}
}
}
menu.pipe.ts
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'menu'
})
export class MenuPipe implements PipeTransform {
transform(value, args:string[]) : any {
let keys = [];
for (let key in value) {
keys.push({key: key, value: value[key]});
}
return keys;
}
}
You do not need a pipe in this case. The answer provided by Robin had a slight error in the inner iteration: <li *ngFor="let menuItem of menu">, you need to specify that the items is a subarray of menu:
<li *ngFor="let menuItem of menu.items">
So your html should look like this:
<div>
<h2>{{menu.name}}</h2>
<div *ngFor="let menuItem of menu.items">
{{menuItem.url}}<br>
<strong> Name: </strong> {{menuItem.id}}<br>
<strong> Title: </strong> {{menuItem.title}}<br>
</div>
</div>
Here's a demo plunker :)
The issue is that you can't ngfor through object object. The way you do it is via filter. Now in the end I created my own pipe, or so call filter. Not sure if it is right, but it worked like a charm.
main-menu.component.html
<ul>
<li *ngFor="let menu of menus | menu">
<a href="{{ menu.menuitem.url }}">
<strong> Name :</strong> {{ menu.menuitem.id }} |
<strong> Title :</strong> {{ menu.menuitem.title }} <br />
</a>
</li>
</ul>
PIPE
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'menu'
})
export class MenuPipe implements PipeTransform {
transform(value, args:string[]) : any {
//return value.filter( item => value[item] != value[item]);
let keys = [];
for (let key in value) {
if(key == 'items'){
for (let a in value[key]) {
keys.push({menuitem: value[key][a]});
// keys.push({menuName: value[key][a].id, menuName: value[key][a].title});
// console.log(value[key][a].id);
}
//keys.push({key: key, value: value[key]});
}
}
console.log(keys);
return keys;
}
}

Resources