Reputation: 131
So I created part of this app that has a modal-window component that is supposed to open when you set the property enabled to true..
application.hbs has this:
{{#modal-window enabled=true title="Manage Admins"}}
{{/modal-window}}
In modal-window.js I have an action closeModal that does this.set('enabled',false)
and likewise to open it, you set it to true.
There is a nav menu on the bottom of the app which uses different components help-link, admin-link, etc. admin-link is also a component with its own hbs and js file. This is how the app was designed. At the bottom of index.hbs:
<div class="configs-list-footer">
{{help-link}}
{{admin-link action='showModal'}}
<div class="logout-link">
<a {{action 'invalidateSession'}} class="tv-icon">
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"><g transform="translate(1.000000, 1.000000)"><path d="M0.347826087,8 L10.7826087,8"></path><polyline id="Stroke-937" points="8 5.2173913 10.7826087 8 8 10.7826087"></polyline><path d="M1.03123478,4.83526957 C2.23471304,2.18831304 4.90253913,0.347617391 8.00027826,0.347617391 C12.2263652,0.347617391 15.6524522,3.77370435 15.6524522,7.9997913 C15.6524522,12.2258783 12.2263652,15.6519652 8.00027826,15.6519652 C4.88862609,15.6519652 2.21036522,13.7952696 1.01453913,11.1288348"></path></g></g></svg>
<span>Logout</span>
</a>
</div>
The action there calls an action in the admin-link.js file but there seems to be no way to tell modal-window to set enabled to true from OUTSIDE of itself which is a basic function of any program.
I cannot for the life of me after searching the Internet for hours figure out how to simply have the 'enabled' property of modal-window set to true when clicking on the admin-link component (which is basically an anchor tag)..
I have found out how to call an action from the Index route, but then just like with component to component I cannot figure out how to change the property of modal-window from the Index route.
Anytime anyone online asks how to do this they are met with "Components should be isolated and unaware of everything else" with no apparent way to do something so basic for a UI.
I'm using Ember 2.12.1
Upvotes: 1
Views: 1154
Reputation: 66343
It's not an answer to your exact question, but the approach we use for modals is to wrap the component in a conditional rather than making it a property of the component. e.g.
{{#if manageAdminsIsOpen}}
{{#modal-window title="Manage Admins"}}
{{/modal-window}}
{{/if}}
and then actions on the controller are used to toggle manageAdminsIsOpen
.
I made an Ember Twiddle showing an example.
Upvotes: 1
Reputation: 3368
I am aware this is an Ember question; but I highly suggest you to go over Quick start documentation of React. There is quite good explanation about component oriented front-end development. One particular phrase exists in Lifting state up section is the following: "Often, several components need to reflect the same changing data. We recommend lifting the shared state up to their closest common ancestor."
This is the case with you now. The state of showing the modal dialog does not belong to modal-window
itself because you need to toggle it from somewhere else. Hence you need to manage this state at the common ancestor; that is the application.js
controller in your case I guess. Hence, actions should be bubbled up to application
controller (I mean even the closing of the modal dialog should be performed by application
controller within an action).
Regarding your question, AFAIK there is not a way you can set a property of a component from within another component. The technique I generally apply is lifting the state up to a common ancestor. Rarely, I prefer to create a service
and define attributes and functions within the service to maintain application-wide state. Hence, if you prefer this second approach you can inject the service into both components and one component can display a state that belongs to the service whereas the other can modify it through functions within service.
You are right about components being isolated. However a component that solely works in isolation is useless; components should accept attributes from owners and should provide actions (events) to work upon. Do not forget to apply data down action up principle and it generally works good with lifting state up principle. This has been a long description; but I hope it will be helpful.
Upvotes: 2