Пропустить входные данные для вложенного компонента в Angular 2
Как можно прозрачно преобразовывать атрибуты из компонента-оболочки в вложенный компонент?
Учитывая, что существует
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 { ... }
Могут ли входы быть переведены в пакетном режиме, поэтому они не будут перечислены в шаблоне?
В приведенном выше коде предполагается воссоздать рецепт для директив 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);
}
}
},
...
};
});
Ответы
Ответ 1
Я не уверен, правильно ли я прав, но вот моя реализация ( 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!)'
}
}
Надеюсь, что это поможет :)
Ответ 2
Вы можете выполнить это, используя @Input() для дочерних компонентов.
http://plnkr.co/edit/9iyEsnyEPZ4hBmf2E0ri?p=preview
Родительский компонент:
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';
}
}
Детский компонент:
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;
}
Компонент приложения:
//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() {
}
}
Ответ 3
Я думаю, что это можно свести к более простой проблеме без Angular2 вообще. Когда у вас есть функция, которая принимает множество параметров, она раздражает и подвержена ошибкам, чтобы указать все эти параметры каждый раз, когда вы хотите их использовать. Проблема ухудшается, когда есть промежуточная функция, которая вообще не заботится об этих параметрах - вы сами добавляете параметры в промежуточную функцию, чтобы она могла передать ее внутренней функции. Yeargh!
Существует несколько шаблонов для решения этой проблемы. Моим любимым является полное копирование внутренней функции и передача экземпляра, уже загруженного с прежними сквозными параметрами, встроенными в него. Я думаю, что http://blog.mgechev.com/2016/01/23/angular2-viewchildren-contentchildren-difference-viewproviders/ - хорошая статья о том, как это сделать в Angular 2, используя @ViewChild
и @ContentChild
. Другая стратегия состоит в том, чтобы обернуть все сквозные параметры в одном объекте, так что, по крайней мере, должен пройти только один параметр. Это также помогает, когда вы хотите добавить больше параметров - поскольку они уже завернуты и прошли непрозрачно, ваш код прохода не нужно изменять.