Could someone tell me how to use destructured data in ng-bind in angular 4+?
I've come across how to use destructured object/array from here .
const wes = {
first: 'Wes',
last: 'Bos',
links: {
social: {
twitter: 'https://twitter.com/wesbos',
facebook: 'https://facebook.com/wesbos.developer',
},
web: {
blog: 'https://wesbos.com'
}
}
};
Trying to bind the data like below:
let {first : f, last:l} =wes;
In the html I simply used {{f}},
but it doesn't show anything. Did I understand wrongly ?
Please refer to what I did: stackblitz
Thanks all
You cannot directly use the object destructuring in angular, because it needs to be binded to the component directly.
Taking your sample, you can do something like this:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular 4';
count = 5;
_destructuring = '';
ngOnInit() {
const tmp = {a: 'hello'};
const {a: _destructuring} = tmp;
this._destructuring = _destructuring;
}
}
Updated example:
https://stackblitz.com/edit/angular-ngmodel-write-value-er4dcv?file=app/app.component.ts
Alternatively, you might want to use Object.assign on angular component's this. However, this would involve writing far much code than needed, so...
EDIT: as requested, here is the sample code with your original object, and the (working) example: https://stackblitz.com/edit/angular-ngmodel-write-value-lf97lr?file=app/app.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular 4';
count = 5;
_destructuring = '';
_nested = {};
ngOnInit() {
const tmp = {a: 'hello'};
const {a: _destructuring} = tmp
this._destructuring = _destructuring;
// Original (nested) object
const wes = {
first: 'Wes',
last: 'Bos',
links: {
social: {
twitter: 'https://twitter.com/wesbos',
facebook: 'https://facebook.com/wesbos.developer',
},
web: {
blog: 'https://wesbos.com'
}
}
};
// Object destructuring (links.social.facebook -> fb, links.social.twitter -> tw)
const {
links: {
social: {
facebook: fb,
twitter: tw
}
}
} = wes;
// Assign to the local property, available in the component.
Object.assign(this._nested, {
fb: fb,
tw: tw
});
}
}
Well seems to work great :
const person = {
first: 'John',
last: 'Doe',
};
const { first, last } = person;
const { first: f, last: l } = person;
console.log(first, last);
console.log(f, l);
Related
Lets say I have variable call myvariable and I want to update the value from 1# boolean to 2# object
export class controller extends component {
1# let myvariable = true;
2# click event would update this.myvariable = { dataNew = 20 }
3# dataView: myvariable ;
}
On 2# I want to update myvariable to an object with value dataNew = 20, will my component understand an update 3# dataView to new value on realtime?
Yes, it's doable although it's not recommended.
Assign myvariable to type any.
import { Component, VERSION } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular ' + VERSION.major;
myvariable: any = true;
update() {
this.myvariable = {dataNew: 20};
}
}
https://stackblitz.com/edit/angular-ivy-spsiuq
const arr = [
'code1',
'code2',
'code3',
'code4',
'code5'
];
const data = [
{
device: 'code1'
}, {
device: 'code2'
} ];
const code = data.map((x: any) => x.device);
const sample = arr.filter((x: any) => code.indexOf(x) < 0);
there's a two data that already created.
which is the device code1 and code2.
what I'm trying to do is. on my side there's a edit.
example i have a list code1 to code 5
then I have two data which is the code1 and code 2.
when I try to edit the data has code 1.
on my list it should display the code1 and the code2 will not displayed.
it should be like this when I try to edit the code1:
[
'code1',
'code3',
'code4',
'code5'
]
Add non constant string to tell what you are currently editing. Also you may need to add exception handing to throw and error if what you are currently editing isn't a viable code.
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular';
public currentEdit: string = 'code1';
ngOnInit() {
const arr = [
'code1',
'code2',
'code3',
'code4',
'code5'
];
const data = [
{
device: 'code1'
},
{
device: 'code2'
}
];
const code = data.map((x: any) => x.device);
const sample = arr.filter((x: any) => code.indexOf(x) < 0 || x === this.currentEdit);
console.log(sample);
}
}
as you know which one to be edited, why cant u use that information and filter out the arr.
import { Component, OnInit } from '#angular/core';
`
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular';
ngOnInit() {
const arr = [
'code1',
'code2',
'code3',
'code4',
'code5'
];
const data = [
{
device: 'code1'
},
{
device: 'code2'
}
];
const toBeEdited = "code1";
let code = data.map((x: any) => x.device);
code = code.filter((data)=>(data!=toBeEdited))[0];
const sample = arr.filter((x: any) => code.indexOf(x) < 0);
console.log(sample);
}
}
`
I have this produced string:
string str = [{"id":1,"name":"Angular"},{"id":2,"name":"SpringBoot"}]
I'd like to convert it to an array of Objects to have that:
listexps: Expertise[];
listexps = [{"id":1,"name":"Angular"},{"id":2,"name":"SpringBoot"}];
And Expertise class is
export class Expertise
{
id: number;
name: string;
}
I tried that:
let array = str .replace('[{','').replace('}]','').split("},{").map(String);
but that didn't resolve my problem, I got:
"id":1,"name":"Angular","id":2,"name":"SpringBoot"
instead of
[{"id":1,"name":"Angular"},{"id":2,"name":"SpringBoot"}];
Have you please any idea about solving that ?.
Big thanks.
What you need is JSON.parse; it converts string to an object;
relevant ts:
import { Component } from '#angular/core';
export class Expertise {
id: number;
name: string;
}
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular';
strIntoObj: Expertise[];
constructor() {
let str: string = '[{"id":1,"name":"Angular"},{"id":2,"name":"SpringBoot"}]';
this.strIntoObj = JSON.parse(str);
console.log(this.strIntoObj);
}
}
complete working stackblitz here
I have two page components that use the same methods with the exception of using two different type classes. The two components are called Services and Users. Both components use templates that are very similar with the exception of the class property info it displays. It seems to be inefficient to repeat methods on both controllers, is there a way to combine/share controllers.
Services.ts
import { Component } from '#angular/core';
import { CORE_DIRECTIVES } from '#angular/common';
const template = require('./service.component.html');
const style = require('./service.component.css');
interface Service {
id: number;
name: string;
summary: string;
path: string;
};
#Component({
selector: 'admin-services',
directives: [ CORE_DIRECTIVES],
template: template,
styles: [ style ]
})
export class ServiceComponent {
services = Services;
selectedService:Service ;
constructor() {
}
onselect(service:Service){
this.selectedService = service ;
}
onEdit(service:Service){
console.log("Edit: "+service);
}
onDelete(service:Service){
console.log("Delete: "+service);
}
onView(service:Service){
console.log("View: "+service);
}
onAdd(){
this.selectedService = <Service>{};
}
}
User.ts
import { Component } from '#angular/core';
import { CORE_DIRECTIVES } from '#angular/common';
const template = require('./users.component.html');
const style = require('./users.component.css');
interface User {
id: number;
image: string;
name: string;
email: string;
role: string;
};
#Component({
selector: 'admin-users',
directives: [ CORE_DIRECTIVES],
template: template,
styles: [ style ]
})
export class UsersComponent {
users = Users;
selectedUser:User ;
constructor() {
}
onselect(user:User){
this.selectedUser = user ;
}
onEdit(user:User){
console.log("Edit: "+user);
}
onDelete(user:User){
console.log("Delete: "+user);
}
onView(user:User){
console.log("View: "+user);
}
onAdd(){
this.selectedUser = <User>{};
}
}
Yep, this is where Angular's component-driven design and Typescripts's class-driven design really shine:
Having defined a ServicesComponent as you have above, you can simply extend that class and attach different component metadata to it:
#Component({
selector: 'admin-users',
directives: [ CORE_DIRECTIVES],
template: template,
styles: [ style ]
})
export class UsersComponent extends ServicesComponent {
constructor(){
super();
}
//override whatever methods/fields in the parent class you need to (and only those)
}
I believe you can create a service with a single set of methods and pass in an object. Then cast the object to the desired class and use it in the method.
i'd like to join the data on init from my customers table into the projects list.
Model is like this:
projects
key
name: string
customer : customerKey
customers
key
name: string
Do you have an example, how i do this from angular2 component using angularfire2?
my controller looks like this:
import { Component, OnInit } from '#angular/core';
import { Project } from '../project';
import { Router } from '#angular/router';
import { FirebaseAuth } from 'angularfire2';
import { AngularFire, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2';
import { Observable } from 'rxjs';
#Component({
moduleId: module.id,
selector: 'app-projects',
templateUrl: 'projects.component.html',
styleUrls: ['projects.component.css']
})
export class ProjectsComponent implements OnInit {
projects: FirebaseListObservable<any[]>;
customers: FirebaseListObservable<any[]>;
projectName: string;
constructor(
private router: Router,
private af: AngularFire
) { };
ngOnInit() {
this.projects = this.af.database.list('projects');
}
add(projectName: string) {
this.af.database.list('projects')
.push({ name: projectName, id: '123' });
this.projectName = null;
}
}
Update
i've changed the type of this.projects to Observable from FirebaseListObservable
my on ngOnInit() method looks now like this:
ngOnInit() {
this.projects = this.af.database.list(`projects`)
.map(projects => {
projects.map(project => {
this.af.database.object('customer/' + project.customer + '/name')
.subscribe(customer => {
project.customer = customer;
})
return project;
})
return projects;
});
}
i can now access not the name property of customer from the template inside of
<li *ngFor="let project of projects | async">
project.customer.$value
Not exactly sure how your dataset looks like, so I'm just going to write a basic example. Assuming a structure something like this:
- projects
- key
- name: string
- customers
- customerKey: boolean
- customers
- key
- name: string
Example data
- projects
- projectId1
- name: "Cool project!",
- customers
- customerId1: true,
- customerId2: true
- projectId2
- name: "Another cool project!",
- customers
- customerId2: true,
- customerId3: true
- customers
- customerId1
- name: "John Smith"
- customerId2
- name: "John Doe"
- customerId3
- name: "John John"
So we're storing the customers' key in every projects' customers property.
Let's say we want to list every projects, but we also want to get the customers' real name as well, not just their id. Since firebase doesn't have joins we'll have to do this manually. Here's one way to do it:
this.projects = this.af.database.list(`projects`)
.map(projects => {
return projects.map(project => {
project.customers.map(customer => {
this.af.database.list(`customers`)
.subscribe(c => {
customer = c;
});
});
return project;
});
});
The inner .subscribe could be changed to a simple .map if you want to get the data asynchronously (in this case use the async pipe in the template`).