Since I have begin to learn Angular 2 , I am following the basic concepts well. But when I tried running the below program, I don't get the values which is statically set in the code.
import { Component,Input } from '#angular/core';
export class Hero {
id: number;
name: string;
}
hero: Hero = {
id: 1,
name: 'Windstorm'
};
#Component({
selector: 'my-app',
template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2><div><label>id: </label>{{hero.id}}</div><div><label>name: </label>{{hero.name}}</div>'
})
export class AppComponent {
title = 'Tour of Heroes';
hero = 'Windstorm';
}
Can someone please point out where I am wrong, also can someone show how to debug the Angular code so that I can learn the framework well and try complex things out by self-learning and solve out basic issues by myself?
The output which I got
This should work
#Component({
selector: 'my-app',
template: '<h1>{{title}}</h1><h2>{{hero.name}} details!</h2><div><label>id: </label>{{hero.id}}</div><div><label>name: </label>{{hero.name}}</div>'
})
export class AppComponent {
title = 'Tour of Heroes';
hero: Hero = {
id: 1,
name: 'Windstorm'
};
}
With hero = 'Windowstorm'; {{hero.name}} is invalid because hero doesn't have a name property.
I'm sure your browser console show an error message. Please add such errors to future questions.
Related
In React Fullstack by Accomazzo book, in the first chapter they used seed.js as a data source. it has IIFE and they used window object to use it anywhere in the project. but when i created my own react project and followed along the codes it shows an error saying Seed is not defined no-undef
I have tried importing, including the js file in html file but those didn't seem to work
this is the app.js file
import React from 'react';
class PlayerList extends React.Component {
render() {
const player = Seed.players[0]
return (
<div className='ui unstackable items'>
<Player
id={player.id}
name={player.name}
club={player.club}
url={player.url}
votes={player.votes}
submitterAvatarUrl={player.submitterAvatarUrl}
playerImgUrl={player.playerImgUrl}
/>
</div>
)
}
}
this is the seed.js file
window.Seed = (function () {
function generateVoteCount() {
return Math.floor((Math.random() * 50) + 15);
}
const players = [
{
id: 1,
name: 'CR7',
club: 'Juventus',
url: '#',
votes: generateVoteCount(),
submitterAvatarUrl: 'images/avatars/profile-pic.jpeg',
playerImgUrl: 'images/players/CR7.jpg',
},
{
id: 2,
name: 'LM10',
club: 'Barcelona',
url: '#',
votes: generateVoteCount(),
submitterAvatarUrl: 'images/avatars/kristy.png',
playerImgUrl: 'images/players/LM10.jp',
},
{
id: 3,
name: 'MS10',
club: 'Liverpool',
url: '#',
votes: generateVoteCount(),
submitterAvatarUrl: 'images/avatars/veronika.jpg',
playerImgUrl: 'images/players/MS10.jpg',
},
];
return { players: players };
}());
Here you can find a working example, just import your seed file. Basically, you only need to import 'seed' and to avoid errors add window.Seed
https://codesandbox.io/s/stackoverflow-import-iife-5mojf
I am still trying to learn what seems to me like advanced Angular 5. The below code does enter the "id" number from the array into the url as expected, but when I go to model/1 it shows my all the objects from the array. I need to only see the object under id 1 and same for each object in the array. I have found so much conflicting information online, from mapping to queries that I'm not even sure where to being and everything I've tried has led to no better results. I have included all the code I'm working with.
I have an array of objects in my json file-
[
{
"id": 1,
"label": "Metal Man",
"sample": "/assets/img/metalman1.png",
"fab": "https://sketchfab.com/models/1b3cb7f8a77145bc8616075e9036b025/embed",
"img1": "/assets/img/metalman1.png",
"img2": "/assets/img/metalman2.png",
"img3": "/assets/img/metalman3.png"
},
{
"id": 2,
"label": "Magrot",
"sample": "/assets/img/magrot1.png",
"fab": "https://sketchfab.com/models/e20c8ade2f16452ca7f440aa84fc8e33/embed",
"img1": "/assets/img/magrot1.png",
"img2": "/assets/img/magrot2.png",
"img3": "/assets/img/magrot3.png"
},
{
"id": 3,
"label": "Baseball and Bat",
"sample": "/assets/img/ball1.png",
"fab": "https://sketchfab.com/models/781c60d3449b46f996a081ae36c20cce/embed",
"img1": "/assets/img/ball1.png",
"img2": "/assets/img/ball2.png",
"img3": "/assets/img/ball3.png"
}
]
My template for each of the above objects-
<div class="columnFlex mainBlock" *ngFor="let model of modelwork">
<div class="modelImagery">
<h1>{{ model.label }}</h1>
<iframe [src]='sanitizer.bypassSecurityTrustResourceUrl(model.fab)'
frameborder="1" allowvr allowfullscreen mozallowfullscreen="true"
webkitallowfullscreen="true" onmousewheel=""></iframe>
<img [src]="model.img1" />
<img [src]="model.img2" />
<img [src]="model.img3" />
</div></div>
And my Activatedroute set up-
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { CommonModule } from '#angular/common';
import { DomSanitizer } from '#angular/platform-browser';
import { ActivatedRoute } from '#angular/router';
import { Router } from '#angular/router';
#Component({
selector: 'app-model',
templateUrl: './model.component.html',
styleUrls: ['./model.component.css']
})
export class ModelComponent implements OnInit {
modelwork: any;
constructor( private route: ActivatedRoute, private router: Router, private http: HttpClient, public sanitizer: DomSanitizer ) {
this.sanitizer = sanitizer;
this.route.params.subscribe(params => {this.modelwork = params['id'];});
}
ngOnInit(): void {
this.http.get<any>('./assets/models.json').subscribe(
data => {
this.modelwork = data;
})
}
}
Any clarification on what I'm needing to do would be so appreciated! I'm trying to learn Angular in days and it is more complicated than I had expected. Thank you for taking the time to look at this!
I don't see anything advanced here. You simple have two asynchronous operations that both set the variable 'modelwork'. One of the operations sets modelwork to an integer and the other sets it to a json array. depending on which operation resolves first.
Edit
Looking at your comment, i see what you want to do. Here's an example:
chosenIndex: any;
modelwork: any;
constructor( private route: ActivatedRoute, private router: Router, private http: HttpClient, public sanitizer: DomSanitizer ) {
this.sanitizer = sanitizer;
}
ngOnInit(): void {
this.route.params.subscribe(params => {
this.chosenIndex = params['id'];
this.http.get<any>('./assets/models.json').subscribe(data => {
this.modelwork = data.filter(d => d['id'] == this.chosenIndex);
})
});
}
Modelwork will now contain an array of 1 object. The one object you want. You can alter this example to get whatever output you want.
Situation
I currently write a news reader app for a magazine, which publishes the content in English and German under different categories. The number of categories per language is different. The categories are stored in as an array per language.
CATEGORIES_EN = [
{
selector: '*',
blog: BLOG_EN,
id: `${BLOG_EN}_*`,
},
{
selector: 'Politics',
blog: BLOG_EN,
id: `${BLOG_EN}_Politics`,
},
// ... 8 more
];
CATEGORIES_DE = [
{
selector: '*',
blog: BLOG_DE,
id: `${BLOG_DE}_*`,
},
{
selector: 'Politik',
blog: BLOG_DE,
id: `${BLOG_DE}_Politik`,
},
// ... 9 more
];
The screen component is always the same, but must receive the selector and the blog somehow.
Question
How can I change the number of screens, when the the language has changed?
How can I assign the categories to the screen component?
Environment
react-navigation: 1.0.0-beta.11
react-native: 0.45.0
Git-Issue
https://github.com/react-community/react-navigation/issues/1872
I've found a solution and want to share it with you:
You have to recreate the TabNavigator all the time when something has been changed.
For details please look in my Git-Issue and the referenced issue.
I am trying to get a user details from a angularFire2 database. Therefore instead of using the FirebaseListObservable, I am using FirebaseObjectObservable since I am expecting just a user from the path.
This is the path and the colums through which I am deriving the user data
path: /projects/users/
columns: userID,username
data
userID:"001",
username:"Icomin"
And this the home.ts
import { Component } from '#angular/core';
import { NavController,AlertController,ActionSheetController } from 'ionic-angular';
import{AngularFireDatabase,FirebaseListObservable,FirebaseObjectObservable} from 'angularfire2/database';
import {Observable} from 'rxjs/Observable';
#Component({
selector: 'my-child-component',
template: `<h1>Welcome {{ (projects | async)}}</h1>` // The template
})
export class HomePage{
projects: FirebaseObjectObservable <any>;
constructor(af:AngularFireDatabase) {
this.projects = af.object(`/projects/users`);
}
I implement the template below, however the returnsWelcome [object object]
The template implementation
template: `<h1>Welcome {{ (projects | async)}}</h1>`
How do I get the user details from the above path and set it into the template
As you mention , you get Welcome [object object] from projects variable. It's mean that you receive a list from this call af.object('/projects/users') .
I dont really know what exactly you want to do with that list but you few options:
1 - show all users in list :
template: ' <h1 *ngFor="let proj of projects | async">{{ proj.username }}</h1>
this will display all user's names , one by one.
2 - show specific user:
(you need to choose the filter criteria: userID or username)
export class HomePage{
project: FirebaseObjectObservable <any>;
constructor(af:AngularFireDatabase) {
this.project = af.list(`/projects/users`,{
query: {
orderByChild: 'userID', //or orderByChild: 'username',
equalTo: <someUserID> // equalTo: <someUsername>
}
});
}
}
and then the template to display the current username:
template: <h1>{{ project.username }}</h1>
Hope it fits what you wanted.
I have a component I'm going to use as a shell for multiple choice questions to load into. Here's how the component is set up so far
component
import { Component } from '#angular/core';
export class Answers{
id: string;
answer: string;
}
const answers: Answers[] = [
{
id: 'exp01q',
answer: 'Its fine as is.'
},
{
id: 'exp02q',
answer: 'I want to make minor adjustments.'
},
{
id: 'exp03q',
answer: 'I want to change my image'
},
{
id: 'exp04q',
answer: 'Ive never wanted to use a particular image until now.'
}
];
#Component({
moduleId: module.id,
selector: 'multi-radio-btn',
templateUrl: 'multi-rad-btn.component.html',
styleUrls: ['multi-rad-btn.component.css']
})
export class MultiRadioBtnShell {
question = 'How do you feel about your current image?';
id = 'exp-img-q';
name = 'exp-ques1';
ans = answers;
}
HTML Template
<h3>radio button shell</h3>
<div class="row justify-content-center">
<fieldset [attr.id]='id' class="card col-8 justify-content-center">
<label class="ques-title">
{{question}}
</label>
<div class="row answer-row-section justify-content-center">
<div *ngFor="let answers of ans" class="col col-12 answer-row justify-content-center">
<div class="col justify-content-center">
<input type="radio"
[attr.id]="answers.id"
[attr.name]="name"
[attr.value]="answers.answer" hidden />
<label [attr.for]="answers.id" class="col ques-ans-title" style="background-color: #4b73a0;">
{{answers.answer}}
</label>
</div>
</div>
</div>
</fieldset>
</div>
The reason it's set up like this now is because the way I was trying to do it at first wasn't working so I went to the Tour of Heroes tutorial to follow along with how they loaded all the heroes. The problem was coming from answer not being defined. So I rigged that part up the same way they did the heroes just for the sake of doing something I'm able to follow just to be sure I get the mechanics of how things load.
The original way I tried to do it was with this
// I had this right above the component
export class ExpQ{
question: string;
id: string;
name: string;
answers:[
{
id: string;
answer: string;
}
]
}
// I had this in the component's class
export const expq: ExpQ[] = [
{
question: 'How do you feel about your current image?',
id: 'exp-img-q',
name: 'exp-ques1',
answers:[
{
id: 'exp01q',
answer: 'Its fine as is.'
},
{
id: 'exp02q',
answer: 'I want to make minor adjustments.'
},
{
id: 'exp03q',
answer: 'I want to change my image'
},
{
id: 'exp04q',
answer: 'Ive never wanted to use a particular image until now.'
}
]
}
]
I was calling it in the html with
{{expq.question}}, {{expq.name}}, {{expq.answers.id}}, {{expq.answers.answer}}, etc.
at first with just loading the question it worked fine, but as I got to the answers: part it started breaking. I came across this https://scotch.io/tutorials/using-angular-2s-model-driven-forms-with-formgroup-and-formcontrol and seen the syntax for the addresses: part was pretty much the same as how I needed to structure my data. So I remade everything to resemble that. I still had no luck getting it to work.
Ultimately I'm going to be sending the questions through the parent component with #input and #output as well as a couple other tricks I came across. But before I can even think about that I need to get a handle on how to put the data all into one source so that it properly reads the nested bits of data. All the examples I come across are simple single tier bits of data, so I'm not sure on the syntax I need to use. How can I make this work?
You can define your model like so:
export interface Answer {
id: string;
answer: string;
}
export interface Question {
id: string;
name: string;
question: string;
answers: Answer[];
}
Then your component could have this to test
question1: Question = {
id: 'q1',
name: 'q1',
question: 'Does TypeScript rule?',
answers: [
{ id: 'a1', answer: 'Yes' },
{ id: 'a2', answer: 'Of Course' },
{ id: 'a3', answer: 'Duh' }
]
};
Of course the names don't have to be the same but I think this gives you a better idea of how to model nested data.
Then to display it you will need to iterate over nested structures. Look up the *ngFor directive. You will want to iterate over your answers in this case. Ex:
<div *ngFor="let answer of question1.answers">
{{answer.id}} - {{answer.answer}}
</div>
Need to flatten the objects,
Params :
Objects : at least n>0 array off JSON objects (dose not matter is circular)
target : {}
path : ""
Note : make sure the Objects Array passed in is n>0 at least
flatten(objects, target, path) {
let me = this;
let retArray = [];
for(let x=0; x < objects.length; x++) {
let object = objects[x];
path = path || '';
target={};
target = me.flattenHelper(object, target, path);
retArray.push(target);
}
return retArray;}
..
flattenHelper(object, target, path){
let me = this;
Object.keys(object).forEach(function (key) {
console.log("key : "+ key + " : object : " + (object[key] && typeof object[key] === 'object') + " path : " + path);
if (object[key] && typeof object[key] === 'object') {
me.flattenHelper(object[key], target, path + key);
}
target[path + key] = object[key];
console.log(target);
});
return target;}