Comment les attributs peuvent-ils être traduits de manière transparente du composant wrapper en composant imbriqué?
Considérant qu'il y a
const FIRST_PARTY_OWN_INPUTS = [...];
const FIRST_PARTY_PASSTHROUGH_INPUTS = ['all', 'attrs', 'are', 'passed'];
@Component({
selector: 'first-party',
inputs: [...FIRST_PARTY_OWN_INPUTS, ...FIRST_PARTY_PASSTHROUGH_INPUTS],
template: `
<div>
<third-party [all]="all" [attrs]="attrs" [are]="are" [passed]="passed"></third-party>
<first-party-extra></first-party-extra>
</div>
`,
directives: [ThirdParty]
})
export class FirstParty { ... }
Les entrées peuvent-elles être traduites par lots afin qu'elles ne soient pas énumérées dans le modèle?
Le code ci-dessus est censé recréer la recette pour les directives Angular 1.x:
app.directive('firstParty', function (thirdPartyDirective) {
const OWN_ATTRS = [...];
const PASSTHROUGH_ATTRS = Object.keys(thirdPartyDirective[0].scope);
return {
scope: ...,
template: `
<div>
<third-party></third-party>
<first-party-extra></first-party-extra>
</div>
`,
compile: function (element, attrs) {
const nestedElement = element.find('third-party');
for (let [normalizedAttr, attr] of Object.entries(attrs.$attr)) {
if (PASSTHROUGH_ATTRS.includes(normalizedAttr)) {
nestedElement.attr(attr, normalizedAttr);
}
}
},
...
};
});
Je ne sais pas si j'ai bien compris, mais voici ma mise en œuvre ( PLUNKER )
const FIRST_PARTY_OWN_INPUTS = ['not', 'passthrough'];
const FIRST_PARTY_PASSTHROUGH_INPUTS = ['all', 'attrs', 'are', 'passed'];
const generateAttributes(arr) {
return arr.map(att => '[' + att + '] = "' + att + '"').join(' ');
}
//-------------------------------------------------------//////////////////
import {Component} from '@angular/core'
@Component({
selector: 'third-party',
inputs: [...FIRST_PARTY_PASSTHROUGH_INPUTS],
template: `
<div>
{{all}} , {{attrs}} , {{are}} , {{passed}}
</div>
`
})
export class ThirdParty {
}
@Component({
selector: 'first-party',
inputs: [...FIRST_PARTY_OWN_INPUTS, ...FIRST_PARTY_PASSTHROUGH_INPUTS],
template: `
<div>
<div>
{{not}} , {{passthrough}}
</div>
<third-party ${generateAttributes(FIRST_PARTY_PASSTHROUGH_INPUTS)}></third-party>
<first-party-extra></first-party-extra>
</div>
`,
directives: [ThirdParty]
})
export class FirstParty {
}
@Component({
selector: 'my-app',
providers: [],
template: `
<div>
<h2>Hello {{name}}</h2>
<first-party [not]="'not'" [passthrough]="'passthrough'"
[all]="'all'" [attrs]="'attrs'" [are]="'are'" [passed]="'passed'">
</first-party>
</div>
`,
directives: [FirstParty]
})
export class App {
constructor() {
this.name = 'Angular2 (Release Candidate!)'
}
}
J'espère que ça aide :)
Je pense que cela peut se résumer à un problème plus fondamental sans Angular2. Lorsque vous avez une fonction qui prend beaucoup de paramètres, il est gênant et source d’erreurs de devoir spécifier tous ces paramètres à chaque fois que vous voulez l’utiliser. Le problème s'aggrave lorsqu'il existe une fonction intermédiaire qui ne se soucie pas du tout de ces paramètres: vous vous retrouvez en train d'ajouter des paramètres à la fonction intermédiaire juste pour pouvoir la transmettre à la fonction interne. Yeargh!
Il existe quelques modèles pour traiter ce problème. Mon préféré est d'instancier complètement la fonction interne et de transmettre l'instance déjà chargée avec les anciens paramètres d'intercommunication intégrés. Je pense http://blog.mgechev.com/2016/01/23/angular2-viewchildren-contentchildren-difference-viewproviders/ est un article de Nice sur la manière de procéder dans Angular 2 en utilisant @ViewChild
et @ContentChild
. Une autre stratégie consiste à envelopper tous les paramètres d'intercommunication dans un seul objet, afin qu'au moins un paramètre seulement soit transmis. Cela est également utile lorsque vous souhaitez ajouter plus de paramètres - puisqu'ils sont déjà encapsulés et passés de manière opaque, votre code d'intercommunication n'a pas besoin de changer.
Vous pouvez accomplir cela en utilisant @Input () sur vos composants enfants.
http://plnkr.co/edit/9iyEsnyEPZ4hBmf2E0ri?p=preview
Composant parent:
import {Component} from '@angular/core';
import {ChildComponent} from './child.component';
@Component({
selector: 'my-parent',
directives: [ChildComponent],
template: `
<div>
<h2>I am the parent.</h2>
My name is {{firstName}} {{lastName}}.
<my-child firstName="{{firstName}}"
lastName="{{lastName}}">
</my-child>
</div>
`
})
export class ParentComponent {
public firstName:string;
public lastName: string;
constructor() {
this.firstName = 'Bob';
this.lastName = 'Smith';
}
}
Composant enfant:
import {Component, Input} from '@angular/core';
@Component({
selector: 'my-child',
template: `
<div>
<h3>I am the child.</h3>
My name is {{firstName}} {{lastName}} Jr.
<br/>
The name I got from my parent was: {{firstName}} {{lastName}}
</div>
`
})
export class ChildComponent {
@Input() firstName: string;
@Input() lastName: string;
}
Composant d'application:
//our root app component
import {Component} from '@angular/core';
import {ParentComponent} from './parent.component';
@Component({
selector: 'my-app',
directives: [ParentComponent],
template: `
<div>
<my-parent></my-parent>
</div>
`
})
export class App {
constructor() {
}
}