Reputation: 28368
I'm making an email modal but I'm having problems actually making the http.post
request. The problem is that post()
is being executed in a child component which means that this.postUrl
is undefined when the function actually runs. How can I make sure that the child component has access to this.postUrl
without passing it to it as an input? The reason as to why I don't want to pass it with an input is that the child component is also used in other places, making the postUrl
too specific to use as an input since it will only be used in this scenario.
@Component({
selector: 'modal-email',
templateUrl: './app/assets/scripts/modules/modal/templates/modal-email/modal-email.component.html',
styleUrls: ['./app/assets/scripts/modules/modal/templates/modal-email/modal-email.component.css'],
inputs: [
'model',
'postUrl',
'header',
'text'
],
directives: [FormInputWithButtonComponent],
providers: [Http, HTTP_PROVIDERS]
})
export class ModalEmailComponent {
constructor(private _http: Http) {
}
post() {
// this.postUrl becomes undefined, this.model is defined since it also lives in the child component
console.log(this.postUrl, this.model);
this._http.post(this.postUrl, {email: this.model})
.map(res => res.json())
.subscribe(
data => this.data = data,
err => console.log(err)
)
}
}
ModalEmailComponent
is being used like this:
<modal-email postUrl="localhost:3000/email"></modal-email>
Inside the modal-email
lies form-input-with-button>
component:
<form-input-with-button [(model)]="email" type="email" [onSubmit]="post"></form-input-with-button>
Child component:
@Component({
selector: 'form-input-with-button',
templateUrl: './app/assets/scripts/modules/form-controls/form-input-with-button/form-input-with-button.component.html',
styleUrls: ['./app/assets/scripts/modules/form-controls/form-input-with-button/form-input-with-button.component.css'],
inputs: [
'model',
'onSubmit' // onSubmit is what calls the post function from ModalEmailComponent
],
host: {
'(input)': 'modelChange.emit($event.target.value)'
}
})
export class FormInputWithButtonComponent {
@Input() model: string;
@Output() modelChange: EventEmitter = new EventEmitter();
}
FormInputWithButtonComponent
template:
<input [(ngModel)]="model" class="form-input-with-button">
<button (click)="onSubmit()" class="form-input-button">Submit</button>
EDIT: Can you extend components? Something like:
export class FormInputWithButtonComponent extends ModalEmailComponent
When I tried it said Cannot read property prototype of undefined
which makes me think that this is not possible.
Upvotes: 1
Views: 2461
Reputation: 2576
Actually, you can inject parent component properties, values from your child component without using any services or inputs.
First, you need to inject Injector
from a constructor in a child component:
export class ChildComponent implements OnInit {
constructor(public injector:Injector) {
}
ngOnInit() {
let parentComponent = this.injector.get(ParentComponent);
this.postUrl = parentComponent.
}
}
Imports
import {Injector} from "angular2/core";
import {OnInit} from "angular2/core";
Upvotes: 5
Reputation: 18719
What I suggest you to do, is to create one Service, where you would store the value of the postUrl
, so that it would be accessible in the child. On the other hand, you can use Event Emitter, and set it as follows:
In ChildComponent:
onSubmit(){
EventEmit.emit('get')
}
EventEmit.subscribe(msg=>{
http.post(msg)
})
And in the parent:
EventEmit.subscribe(msg=>
if (msg == 'get') EventEmit.emit(this.postUrl)
);
Of course, thats just pseudo code, so you would need to adjust it to your needs.
Upvotes: 0