I am trying to create a popup dialog which asks for an input and returns the value.
I included a popup component on the root component, above the app's router outlet
In the popup component, I have an open() method which changes a boolean I called "status", which the component has an *ngIf looking at (to control the popup's appearance).
If I create a service and use an Event Emitter, I can not get a return value of the form input.
Any advice?
https://gist.github.com/alshdavid/f783ad367bc1c77cb07412ba0ea2e099
EDIT: I apologise for being bad here - Turns out I had to use a redux-style data model
You've got a small error, in that *ngFor is for iterating through a collection. You want *ngIf instead.
In terms of how you would go about implementing a popup like this, that is quite a broad question. I'll try to put together an example later.
Related
I am having an issue where I am trying to pass state on a link but I keep getting undefined when using the state. My Quiz card layout function takes in the details and then links the page when the button is clicked passing the details as the state. Then in my child/link function, I try using the state.
-- I am trying to pass props in my Link by using the state in which I can then refer to my child/linked function to use the information passed on. I am currently learning React (16.2) and any information would be appreciated thank you. I am using functional components as well would there be a better approach? My initial approach is when the user clicks the button it'll link them to a new tab page and display the information from the previous page via the Link. I will post more info if needed.
In my child/link PetLayout function, I tried using the props to see if it contains the state and the useLocation but both are undefined.
In my App js I have the Route
UPDATE: My issue was the target = '_blank' in this case it works now. Why does the target = '_blank' cause this issue where the state is undefined?
#Daniel S _blank is opening in new tab so its another instance of the app, even the app is same but it works differently internally so I would suggest you to use queryString and localStorage.
I have one ReactJS App which I reduced to the minimum as possible on the diagram below:
Side note: On this App I use Redux to manage state changes.
This App contains:
Component: UploadScreen with an image holder and a button. When that button is clicked, the user gets displayed a Popup Window which let him to pick an image from his device file system. Then that image is displayed on the image holder.
Component: AuxWidget which is a totally different component (needs to be separate) which also contains a button that when it is clicked it should popup the Select File window. I was thinking in something like triggering the click event of the first button.
Any idea on how to achieve that?
First I though about using Redux but I think that's not a too good idea because even though you can send messages with it from one component to another, that causes a render update and I don't want that.
Also, I was thinking on using jQuery but that's not the best approach when it comes to ReactJS.
Also, I thought about using the attribute: ref="foo" to get a reference to the other component but I think that's normally done when you want the interaction to be between parent and child components.
Also, I was thinking about EventEmmitter but I don't know if that's the best approach on this case (I'm using Redux to manage the state changes between components).
One of the best ways I can suggest using RxJS, you can create a Subject and pass it to your components. In one component you will need to subscribe to it and whenever you will call next on your subject from the second component, the other will be notified, so you can trigger open popup. You can even create your own implementation for this in case you don't want to add new library to your project.
The upload window could be triggered when a certain state in the app changes. The relevant state on the app could be changed from different places, like from AuxWidget and UploadScreen. That way they are not coupled with the upload window. They merely call a function that is passed to them and that function changes the state on the app and it will display the window.
If you have a shared component between two unrelated component I think it is best to lift that common component and let its state sit on a higher level.
If I understand things correctly, your primary concern is code-reuse as opposed to wanting to call a sibling method. Basically, you want a SelectFilePopup component that can be re-used (open/closed) cleanly. I think React Portals could be a good solution for this. I found a good example (https://github.com/Assortment/react-modal-component/blob/master/src/components/Modal.js) of how a Modal can be isolated into a component and be called anywhere in the codebase.
The usage of the Modal looks like this (copied and slightly modified from App.js in the github project above)
import Modal from './components/Modal';
<Modal><div>Click me to open Modal</div></Modal>
And the Modal component implementation (simplified)
render() {
return (
<Fragment>
<ModalTrigger
onOpen={this.onOpen}
/>
{isOpen &&
<ModalContent/>
}
</Fragment>
)
}
By default the Modal component shows a trigger (i.e button) when isOpen state is false. Once clicked, and isOpen switches to true, the ModalContent (i.e can be the FilePickerPopup) is dynamically created and attached to document body. You can check out the source code for more details. I think its a very clean solution to modals. So in your case, your code could end up looking something like this
UploadScreen.js
import FileSelectPopup from './components/FileSelectPopup';
<FileSelectPopup>{Upload Image}</FileSelectPopup>
AuxWidget.js
import FileSelectPopup from './components/FileSelectPopup';
<FileSelectPopup>{Upload Image or some other text}</FileSelectPopup>
So basically, AuxWidget doesn't even need to know about where the FileSelectPopup is located at. It's an independent component that can be called anywhere. The caveat is that the Modal implementation in the project I linked to is not a singleton (although it can be modified to be one). So if AuxWidget and UploadScreen are visible to the user at the same time, clicking both Upload Image buttons will create two instances of the Popup.
I would define the function in the parent component and pass it to both children as props
I found this question that is similar, but it did not explain the issue I am trying to solve for. (Using Vue.js 2)
I have an array of objects (users), that I display as a list.
I want to open an "edit user" modal component, which needs to prefill the form values with the user data (exact parent object), but I do not want to edit the parent data until I click a save button that verifies the data before emitting an input event with the new values of the object.
I do not want to manually call out each property to create a new "clean" object (if I change the data type this is a headache), but Vue is adding its reactivity to the user object and therefore modifying the value in the component updates the parent value at the same time.
I also want to wait for the server to confirm a change is saved before emitting the input event; therefore the parent won't update until the data is confirmed on the server.
Is there a recommended pattern for non-reactively modifying props in components, instead using the emitted input event to update, as per the Vue component prop/event specs?
Note: I already have a working example, save for the concern with separating the reactivity bit.
We develop an Ember based framework for internal use of various groups within our organization. Along with this, we maintain a demo page, which displays all the components we've developed along with documentation on how to use the components. I need to modify one of the component demo pages, to allow the user to custom build the component. For example, the component has two properties showCheckboxes and showRadioButtons. By default, showCheckboxes is true, and the component, of course, displays checkboxes. I want to add a select so the user can choose between radio buttons and checkboxes. Everything is wired up correctly and the routes action gets called, but, if I select radioButtons, the component does not refresh and display readio buttons. I've set breakpoints and I see that the route is not called, so the new properties are not read. How can I force Ember to rebuild the component from scratch? I've tried this.refresh() in the route, I've tried setting the model to the new model with the changes, but the component does not redraw with the new properties. I've also tried transitionTo. But if I don't pass a model, nothing happens. But if I pass in the new route, I get this error:
Error: More context objects were passed than there are dynamic segments for the route
I hope this was clear enough for someone to provide some guidance.
Thanks
I found on this page a great example of https://github.com/emberjs/ember.js/issues/11043 how to inherits from a component. Here is the example: http://emberjs.jsbin.com/rwjblue/443/edit?html,css,js,output
I played a bit with and especially with actions and come to this question:
How can I set the context of the component?
Consider the following examples:
http://emberjs.jsbin.com/cofobanoca/edit?html,css,js,output
and a derivate of it
http://emberjs.jsbin.com/gipawemipe/1/edit?html,css,js,output
They are pretty much the same except that in the second link, the component is dynamically create inside an action.
My question is, why is {{this}} in the second example a "generated application controller" and not a "App.XBarComponent"?
EDIT:
Maybe I was not clear.
What I want to achieve is to render a modal which contains inputs fields. This should be rendered inside the application template (using outlet) as a popup over the whole page. The Modal is built with two components just like foo and bar. BaseModal (which is Foo) and LoginModalContent (which is Bar) are better names.
On click on OK (which is defined in BaseModal), I want to call the OK action of LoginModalContent to be able to get the values of the forms (defined in LoginModalContent) using e.g. this.get('username').
They are pretty much the same except that in the second link, the
component is dynamically create inside an action.
There you're not creating a component, just rendering a view, and if you don't specify a controller for a view Ember creates one for you, that's why {{this}} is "generated application controller" in the second example.
That also explains why the action handler of the XBarComponent doesn't work in the second example, since the view is missing the component controller.
If you want to programatically insert components the component helper is your best bet, it renders components by its name while letting Ember handle the view/controller/subcomponents management.