ngSemantic
ngSemantic copied to clipboard
Accessing #myModal from another component
Hi folks, big congratulations for your work! I'd have one question. I'm using the modal component (using classes as a quick fix to the issue brought by the rc6) and imagine to have this situation: Two components, the first one has the button to open the modal, and the second one has the modal that must be opened from the button in the first component.
Now how can I access the template reference variable of the modal from the first component (in order to call #myModal.show()?
I hope you can help, thank you again.
Hi, you can by example output a reference of the modal from the component containing it. And then, you can use it wherever you want :)
Hi, i think I'm missing something here. I know I could use viewchild on the component that contain the modal to output a reference from the template but then to pass it to the other component that has the button should I use the output decorator? Is that the only way?
I know this is due to my lack of knowledge about angular 2. Thank you
This is an opinion related response.
Generally speaking, each component declares Inputs and Outputs, which are ways to define how to interact with them. Let's say your component A contains a button that should open a modal. If the modal is on the same component, it's fairly easy : you just have to retrieve a reference to the modal and show it. If the modal is in another component B, you need to somehow retrieve the modal instance to handle it in the parent or keep an input modal visible state in the B component. The parent which contains both A & B components would do the link, by example :
<a-component (onShowModal)="modalInstance.show()"></a-component>
<b-component (onInit)="setModalInstance($event)"></b-component>
or
<a-component (onShowModal)="setModalVisible(true)"></a-component>
<b-component [modalVisible]="modalVisible"></b-component>
Depends on your style.
You've been very helpful! All clear, thank you again!
EDIT: I did it a little different though. Without using the parent component of both A and B, I did something like:
<button class="ui button green" (click)="groupModal.show()">Click me</button>
<b-component (onInit)="setModalInstance($event)"></b-component>
where groupModal of the button element is a class property set with the modal instance by setModalInstance of the b component.
Hope this isn't considered a bad practice
Another problem (hope to not bother anyone). Considering that there are plenty of modals generated in a ngFor cycle with their buttons, I'd need a way to differentiate the modal references so to open the corrispondent modal attached to its button.
I used to do this before without the ng-semantic module attaching an id to a class and using jquery to show the modal with the right id, but what now?
I thought something like to use the groupModal reference as an array and use the index of the ngFor to access that particular reference (for now I solved it like that), but I'd like to know how I should properly do this, because my solution would be surely way worse than yours.
Regarding the groupModal.show() thing, don't use direct call in html.
Refer to the official style guide, it should be written somewhere :)
HTML should stay lean and concise.
Regarding the modals loop, you can still wrap your button + modal in a new component. This way you won't have to change the way you're handling your reference, plus you will have the common logic in one place.
Right for the component, I overcomplicate things sometimes. (it's also true that creating a new component doesn't always work because break semantic-ui styles)
For the html, this means that I can never use (click) to call function? If so I think that there is no reason to use click ever and at this point why they created it? Even in the example in ng-semantic myModal.show() is called within the html...
Thank you!
@giacomocerquone I had the same requirement and solved it by passing the first component (which contains the modal) into the second component which has the button. The second component calls a method on the first which then opens it.
So on the first component with the modal on it you should import ViewChild from angular/core. Then you can get an instance of the modal like @ViewChild('mdlConfirm') mdlConfirm:any;
Also in the first component make a function 'openModal()' which basically does mdlConfirm.show();
/* Component one - App component */
@ViewChild('mdlConfirm') mdlConfirm:any;
openModal() {
mdlConfirm.show();
}
and then in your second component pass the first component into the constructor, after importing it:
/* Component two - Child component */
import { AppComponent } from '../../app.component';
@Component({
selector: 'app-child',
templateUrl: './child.component.html'
})
export class ChildComponent{
constructor(
private app: AppComponent
) {}
onButtonClick(){
this.app.openModal();
}
}
then in a button click event you can do: this.app.openModal()