Update two input fields in different components with redux - redux

I am trying to get the following behavior in react using redux. I have two side by side components both have a <input> textfield that displays the same value. When I edit either of the field's, I want to dispatch an action and have redux store update the state of my app in both components
Exactly like asana app.
when I edit the field on left it updates the field on the right side as well
and when i edit the field on right, It updates the text field on left as well
I can only get it working one way and not both ways. I am using the value prop of the <input> textfield and keeping a state variable to update the <input> textfield as described in
react-docs.
I have state variable in one component and other one directly listens to the props.
I tried using the defaultValue prop if <input> textfield but it runs into other problems of not updating value when switching between different items

Hard to answer this without seeing your code, but based on what you're saying it sounds like you are storing one input's value on state?
If I want a value to be linked to a global store, I wouldn't store it on state. I'd do something like this (a bit pseudocody but hopefully you get the idea!)
onChange: function (e) {
this.props.dispatch(updateName(e.target.value));
},
render: function() {
return (
<input value={this.props.name} onChange={this.onChange} />
);
}
The dispatch causes an update to the global store which then cascades that updated name value back down to the react component you are currently typing in, as well as the other input elsewhere that is populated by the same data.

Related

Can't get to dynamically style one item from a v-for vue 3

I am trying to get the active item from this menu list to display in a different style. When I reload the page, the style gets applied for a split second, then disappears and all items share the exact same style.
There is a similar thread saying the solution is to actually have the item available as a data property in that component. I have tried that too, and it would not work. It makes more sense to have all the data from a computed property since I am using Vuex for data storing.
The template:
<li class="topic"
v-for="topic in topics"
:key="topic"
#click="selectTopic($event, topic)"
:class="{'active': topic === current}"
>
{{topic}}</li>
and the script:
computed: {
topics: function(){
return this.$store.state.topics
},
current: function() {
return this.$store.state.current_topic
}
},
The current_topic is updated with the selectTopic method in this component. It all works fine, except I can't get the current_topic to have a distinctive style.
Oh, on the styles I simply have .topic.active {border:yellowgreen solid 0.5em;}. If I do topic:active then the style gets applied when I click but only for the time I am clicking (also if I hold), but it does not get applied when reload not even for a split second.
Any leads? thank you :-)
Just as a conclusion / closing of this thread. The code I presented is correct. The problem had to do with a getter which was converting the current_topic into a title. This is why topic and current did not match inside the class binding. I figure it is still worth leaving the thread since it might be helpful for somebody else dealing with class binding inside a v-for.

checkAll, uncheckAll not working properly post user interaction with an individual checkbox

I have recently learnt angular from udemy. I was trying to use this a custom checkbox in my angular app. The problem is not with the checkbox itself but the ui not getting updated on checkAll, uncheckAll after user interaction with an individual checkbox
My implementation on stackblitz
Things i have tried:
using timeout (i have used it to get autofocus working)
using ChangeDetectorRef detectChanges()
using template forms but tr/tbody won't render even if i wrap tbody in it
using reactive forms (not very sure if i did it correctly)
Steps to reproduce:
click on any checkbox but the first one.
click on the first checkbox checkAll, uncheckAll... It doesn't work on the checkbox clicked in the first step.
The checked attribute describes the default state of the field. Removing it will have no effect if the field has been interacted with (or if its checked property has already been modified). сhecked property can be modified by user interaction(click on checkbox)
You should be manipulating checked property instead since it represents the current state.
checkAll() {
const inputs = document.querySelectorAll<HTMLInputElement>('input[type=checkbox]');
inputs.forEach(input => input.checked = true)
}
uncheckAll() {
const inputs = document.querySelectorAll<HTMLInputElement>('input[type=checkbox]');
inputs.forEach(input => input.checked = false)
}
Forked Stackblitz
Note: this is not quite Angular way to work with form controls. You shouldn't be touching DOM directly in order to update control value

How to use MobX obervables to cause a 3rd party React Component (FullCalendar) to render?

I am trying to wrap FullCalendar React component with my own functional React component with useContext hook to access MobX store (I might use the store in other components eventually) and observer() to make it react to changes in the store. My component reacts as I would expect, but I have trouble making the FullCalendar component render after a change.
I've tried finding a solution, wrapping <FullCalendar> in <Observer>, playing with autorun() and reaction() but nothing worked. I have to be missing something
This sandbox https://codesandbox.io/s/mobx-fullcalendar-xejn9 shows a simplified version of my solution so far.
Clicking the button at the top adds an event to the observable store, which gets shown in a list below it. But the calendar doesn't show the new event.
Weirdly enough if I make a change in the code, save it, the CodeSandbox causes the render and the events show up in the calendar.
Thanks to #ADyson, I found a solution. Instead of passing a static list of events to the FullCalendar component
events={store.events}
I can pass an event fetching function. So in the most trivial case, I can just pass the events from the store to the successCallback function and it works.
events={(fetchInfo, successCallback, failureCallback) => {
successCallback(store.events);
}}
I've updated the CodeSandbox https://codesandbox.io/s/mobx-fullcalendar-xejn9 as well.

I need to access to input inside InputGroup BlueprintJs react component

The BluePrintJS React InputGroup component is great and convenient for modern user-interface. But unfortunately the React component do not allow access to the <input> element inside.
I need to access the input element for 2 main reasons :
if I have 50 InputGroups in my form, I don't want to write 50 OnChange() callbacks. When the user finishes all inputs, I want to get all InputGroup.value(), which is not possible (it is possible with regular input element thanks to HTMLInputElement.value, but InputGroup does not allow accessing internal input)
At form displaying, I need to focus on first field. InputGroup has no function focus(), while HTMLInputElement has one.
Briefly there are 2 functions missing in InputGroup : GetValue() and Focus() , and I cannot see why they are missing.
Any suggestion will be greatly appreciated.
Thanks a lot.
I found the way of getting the input ! with :
inputRef={(input:HTMLInputElement) => {
this.logininput=input;
}}
(didn't see it at first time).
Now I have the input object, I can set focus at "didmount", and I can get the value with logininput.value.
Thanks
Slightly different variation but this works too:
inputRef:(input:HTMLInputElement | null) => {
// your code here
return input;
}
}}
just be aware that code runs when you just render the component, depending on your usage, to me happens when I click the child control on a select.
In my case, I just wanted to modify an input that works for text search on a select.

Google Appmaker: Update form based on selected dropdown option

I have an AppMaker app that has a from based off of one address table/datasource. I can get a form with next/prev buttons, but replaced the key field (name) with a dropdown list of all names (a user can start typing names to jump there, with the dropdown showing).
My hope is that when a user selects from the dropdown, the entire form updates and the next/prev buttons work properly as well (there too many records to page thru with next/prev only). I don't have to have next/prev functionality if it complicates things too much.
Currently the dropdown is working, but I cannot get the index for the next/prev buttons set or the rest of the form to reflect the selected dropdown record.
I've tried to set the "onValueEdit" event to something like this...
var selected = widget.value;
var idx = widget.options.indexOf(selected);
console.log("Selected: "+selected+", index = "+idx+"\n");
if(idx < 0) { //...this error is never hit
console.log("Index error - setting to zero!\n");
idx = 0;
}
widget.datasource.loadPage(idx); //...update form?
Two observations via console logging:
The "idx" var is never set to the selected dropdown index reliably, and is
often "0" (tho no error msg ever shows), so the "indexOf()" function
isn't working as expected.
The "selected" var (name) is always correct.
If I call widget.datasource.loadPage(...) with a fixed value (say 5) it has no effect on what is shows in the form either (previous loaded data remains) - obviously not the way to do it :v/
Can you steer a noob in the right direction?
If you are using default App Maker form, then you can see that so-called pager, doesn't actually paginate. It triggers prevItem/nextItem datasource methods, in other words it navigates through datasource items, not pages. Here is a quote from App Maker docs:
nextItem: Selects the next item. For Query Datasources, if the current item is the last item on the page, then this loads the next page and selects the first item on the newly loaded page.
So, if you already have all your items loaded(you set query page size for your datasource to 0), then you need just to change selected item within datasource:
// onValueEdit dropdown event
// assuming, that form and dropdown share same datasource
widget.datasource.selectKey(newValue._key);
If you really have lots of items and it is not feasible to load all of them in one call... then it will be all another story...
UPDATE:
It's important that Options and Value are set as shown in the image below!
However, I had trouble setting them that way (read: wasted hours!) until I wiped them both completely using More options in the binding picklist, and tried again (I had even tried on a brand new app!). I was being forced to choose ..projections.. and then a final field before the OK button would be available.
Not sure if AppMaker is buggy here or there is something simple I'm not understanding!
None of the coding in my original question is required.
Once set this way, binding just works as you would expect it!!
All other fields are set as #datasource.item. and are bound to whatever item is chosen. No Events settings are necessary for the dropdown either, as I thought they might be.
I deleted this page and started again, and replaced the default business name data field with a drop down, I set the dropdown as:
Options: #datasources.Addresses.items
Value: #datasources.Addresses.item
It works fine?! Not sure what happend in my original page!
UPDATE:
So it seems you need to delete both the Value and Options and then re-enter these. The OK will light up when you do.
Also, my original take on App Maker was to build the UI and attach data. That was my first mistake. You build the data then have App Maker build edit/add pages for you.

Resources