2016-02-25 13 views
6

Non capisco davvero come funziona il binding degli oggetti, quindi se qualcuno potrebbe spiegare se posso usare @Input() all'interno di una classe base, o meglio: decoratori ed ereditarietà. Ad esempio se ogni modulo deve ricevere un cliente Ho una classe di base:@Input e altri decoratori ed ereditarietà

export class AbstractCustomerForm{ 

@Input() customer; 
... 
} 

e quindi estendo questa classe in una componente reale:

export AwesomeCustomerForm extends AbstractCustomerForm implements OnInit{ 
    ngOnInit(){ 

     if(this.customer) 
      doSomething(); 

    } 
} 

ma questo non funzionerà, il Cliente non vengono mai impostare :(

risposta

7

aggiornamento

L'ereditarietà è adeguatamente supportato dal 01.232.411,793863 millions

originali

Decoratori non vengono ereditati. Devono essere applicati alla classe utilizzata come componente direttamente. I decoratori delle sottoclassi vengono ignorati. L'ho visto menzionare che @Input() o @Output() funzionano se solo la super-classe li ha e la sottoclasse non ne ha.

+0

Quindi devo scrivere ogni ingresso comune in ciascuna delle forme cliente :( – Silencer

+1

Yup, spero che migliorano questo alla fine ma è un argomento complicato perché ha bisogno di essere compatibile con Dart e JS e non deve impedire la compilazione per applicazioni enormi (per esempio di Google intern.) Probabilmente non qualcosa che sarà corretto per 1.0. –

+0

È bruciato da questo - errore piuttosto criptico anche i messaggi, lamentandosi di un campo indefinito, hanno scoperto che i decoratori non sono ereditati a meno che non ci siano decoratori nella classe dei bambini. Sembra che le informazioni dei decoratori siano state aggiunte alla definizione della classe, ignorando quelle della superclasse, e la ricerca di decoratori non segue la catena. In ogni caso, l'unico modo è di COPY tutte le proprietà decorate dalla superclasse alla classe bambino. –

5

Una strategia che sto seguendo è qualcosa di simile:

@Component({ 
    selector: 'my-component', 
    template: `......`, 
    inputs: MyAbstractComponent.genericInputs 
}) 
export class MyComponent extends MyAbstractComponent { 

    @Input() width: number = 200; 
    ........ 
} 

dove:

export abstract class MyAbstractComponent { 
    public static genericInputs : string[] = ['base']; 
    public base: String; 
} 

quindi, MyComponent otterrebbe base così come width binding. In effetti, penso che ci sia ancora spazio per migliorare usando la riflessione.

0

I decoratori non sono ereditati, ma la classe lo è. Così la mia soluzione era questa:

@Component({selector: 'a') 
class A { 
    @Input() field; 
} 

@Component({selector: 'b', inputs: ['field']} 
class B extends A { 
} 
0

mi sono imbattuto in questa domanda, e solo voluto sottolineare che a partire da Angular 2.3.0-rc.0 questo è in realtà possibile.

Semantica eredità

Decoratori:

1) Lista dei decoratori della classe e dei suoi genitori nella antenato primo ordine

2) usare solo l'ultimo decoratore di ogni tipo (ad esempio @Component/...)

parametri del costruttore:

Se un la classe eredita da una classe genitore e non dichiara un costruttore , eredita il costruttore della classe genitore, e con esso i metadati dei parametri di quella classe genitore.

ganci Ciclo di vita:

seguire il normale modello di ereditarietà di classe, vale a dire ganci del ciclo di vita delle classi genitore saranno chiamati anche se il metodo non viene sovrascritto nella classe figlia.

https://github.com/angular/angular/commit/f5c8e09

2

Anche in angolare 4.2.4 funziona bene in modalità dev. Ma quando si fa una build prod (ng build -prod) viene a mancare:

ERROR in Template parse errors: 
Can't bind to 'step' since it isn't a known property of 'app-textarea-step'. 
1. If 'app-textarea-step' is an Angular component and it has 'step' input, 
then verify that it is part of this module. 
2. If 'app-textarea-step' is a Web Component then add 
'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to 
suppress this message. 

La mia componente si presenta come:

abstract class StepComponent { 
    @Input() step: BaseStep; 
    @Output() next = new EventEmitter<string>(); 
    @Output() answer = new EventEmitter<Answer>(); 
} 

abstract class SingleNextStepComponent extends StepComponent { 

    onSubmit(answer: string) { 
    // ConfirmStep heeft geen answer. 
    if (answer) { 
     this.answer.emit({ question: this.step.key, value: answer }); 
    } 
    const step = this.step as SingleNextStep; 
    this.next.emit(step.next); 
    } 
} 

// Decorator inheritance works in standard build (ng build) but fails in production build (ng build -prod) 
// Workaround: inputs element on @Component that contains the inputs..... 
@Component({ 
    selector: 'app-textbox-step', 
    templateUrl: './textbox-step.component.html', 
    inputs: ['step'] 
}) 
export class TextboxStepComponent extends SingleNextStepComponent { } 

@Component({ 
    selector: 'app-textarea-step', 
    templateUrl: './textarea-step.component.html', 
}) 
export class TextareaStepComponent extends SingleNextStepComponent { } 

Fortunatamente la soluzione funziona. Gli input aggiunti a TextBoxStepComponent hanno impedito a questo di fallire, passando a quello successivo, non ancora fornito di "input".

Ma 'ng build' funziona benissimo senza bisogno di input sui decoratori @Component ...

+0

Grazie mille! Sai se questo è già stato risolto o se c'è un bug ticket per questo? – Sebastian