How to bind and emit data simultaneously in Vue? - javascript

I am using Laravel framework with Vue. I have a parent component which has a child component. The child component has a list of checkboxes, and whatever checkbox I tick, the value gets appended (or removed) from an array stored in data(). I am able to bind the input correctly to the array in the child component, but when I am emitting this array back to the parent component, the data is not fresh, ie it emits back an array with the result of the previous checkbox I ticked, not the current one.
I wanted to know how to introduce a kind of delay between data binding and data-emitting so that I can emit back accurate data.
Child Component
<input type="checkbox" :id="color" :value="color" v-model="colors" #click="$emit('color', colors)" />
data() {
return {
colors: []
}
},
Parent Component
<Child v-on:color="updateColors" />
data() {
return {
colorList: []
}
}
updateColors(colors) {
this.colorList = colors;
}
Output: When I first click on Red, the array emitted back is empty, when I then click on another color like Blue, then the array emitted back only has "Red".
Can someone help me out in binding data and emitting the same data simultaneously, or if not possible then introducing a delay which helps me to first save the data into the array and then emit the modified array back to the parent component?

You can watch data properties in Vue and perform a function when they are changed. For example, in your child component you could watch the property colors and emit the color event only colors is changed;
watch: {
colors: function(){
this.$emit('color', this.colors);
}
}

One option would be to change the event that emits the data.
Currently, you emit when click happens. But that is, as you mentioned, before the data is updated. To fix your problem, you could simply change the event to #change.
In any case, I would recommend you use a store to keep data between components in sync.
You can have a look at VueX for example, or build your own store. A handy feature to build your own store can be the newly integrated Vue.observable from Vue 2.6, see the documentation

Related

ReactiveSearch's ReactiveList does not update on ES changes

I have an Elasticsearch cluster into which realtime events pour in. What I thought I'd be able to achieve is to show the events as they come in inside a ReactiveList in ReactiveSearch. This is what I roughly have:
class App extends Component {
render() {
...
return {
<div>
<ReactiveBase
app="my-index"
url="my-secret-es-cluster"
>
...
<ReactiveList
componentId="Results"
dataField="time"
sortBy="desc"
stream
react={{
and: ['SensorX', 'SensorY'],
}}
onData={(res) => <div>{res.time}: {res.some.field_of_interest}</div>}
/>
</ReactiveBase>
</div>
}
}
}
Whenever I make a change in one of the sensors (i.e. filters) I can see the changes reflected in the ReactiveList component. However, they don't update whenever the database changes, which I had assumed it would do with stream enabled:
This list can reactively update itself based on changes in other components or changes in the database itself.
Two questions:
Have I misunderstood how this component is supposed to work, or do I need to do something else before I can see updates to the ES cluster reflected automatically in the results?
Is it possible to not load results unless a certain sensor is set/selected (e.g. from a DataSearch component)?

Vue Material - Triggering MdTableAlternateHeader visibility

I'm looking for a way to trigger the MdAlternateHeader visibility - or maybe to reset its count state.
The app in question has this multi-selection MdTable in which I implemented a delete function per row. But on data erasing, the alternate header still hold the md-selected class set to true (refeered to the deleted and previously selected element/row). As well as the related computed props (isInSelectedItems and isMultipleSelected).
How can I change these state? I was thinking about to trigger a "selected" or "clicked" event on the row befote its deletion, but I'm missing something on the way.
Thanks in advance for the help.
Ok, I got it.
I inspected the framework data and noticed this md-selected-value prop, contained in MdTable component. After declaring the prop in my component:
props: [
// ...
'mdSelectedValue'
],
I update its value through a second array, delegated to track what elements are being selected for deletion:
data: () => ({
selezionato = []
})
then I listen for any change in selection:
<md-table v-model="cercato" #md-selected="onSelezionato" md-sort="codice" md-sort-order="asc" md-card md-fixed-header :md-selected-value="selezionato">
In my delete function, after every deletion I reset the the new selezionato value, in order to disable the alternate header:
this.selezionato = []
That's it.

Added component contains old data

I don't understand what's happening here. I dynamically am adding a component to a parent template. The thing I don't understand is that for some reason the newly added component carries old data on the first click, and then updates with the latest data on the second click. I am assuming that the new component would also have the new data, but it does not. You can see this happening on my site.
Just open the console and you can see the count. Click on the red button to add components. Then the first time you click on a new component it reverts back to old data, click again it moves to the latest data.
Here is my code: This gets triggered on click inside my component, with this.counter emitted to my parent template. Counter as a data element is defined on my component.
methods: {
sendCounter() {
this.counter++;
console.log("What's my counter " + this.counter);
this.$emit('newComponent', this.counter);
},
Then this is the receiver in my parent template:
<marketplace #myError="notice = $event" #newComponent="components = $event++" v-for="(item, index) in components" :index="index"></marketplace>
EDIT:
It seems like the data element is also getting re-created everytime I add an additional component. The weird thing is that it "catches up" the counter to the current count.

React.JS, pass data between components

very new to react. you can say I have not yet started to think like React.
here is the problem:
<div>
<DropDown> </DropDown>
<Panel> </Panel>
</div>
In the dropdown, I select a value. Store it in state, as something as , currentLocation.
Then I go to Panel, hit a button, and I want to open a modal. When i open a modal, I need to pass the currentLocation to that model.
I can pass in arbitrary value to modal, but I cannot figure out a way to get the currently selected item from DropDown.
How do I get the value of the currently selected item to the Panel?
Am I even making sense?
When you call the setState in the dropdown that will force an update of the page.
Then if you call this.state in your component you should have the value you need there.
You should go over the basic tutorials to grasp the react basics.
But it goes like this:
getInitialState: function() {
return {
myVar: ''
//set your variables here
//getInitialState will get called before the component gets mounted
};
},
myCustomFunction: function(newVariable) {
this.setState({
myVar: newVariable
});
},
render: function() {
return (
<div>
<input
onChange={this.myCustomFunction}
/>
<MyCustomComponent myProp={this.state.myVar}/>
//everytime the state changes MyCustomComponent will have that new value as a prop
</div>
);
}
There is a lot of ambiguity in your question but I'll try for the simplest case.
You have a Panel component and a Dropdown component.
You want to the Panel to have access to a value that was set when the Dropdown was used.
Solution: When the Dropdown is actuated, it creates an Action that Stores the selected value.
When the modal button in the Panel is actuated, it creates an Action that requires the DropDownStore. Then it decides what to do based on that value.
The pattern I am loosely describing is known Facebook's Flux architecture which is basically just a more specific application architecture for React applications similar to pub/sub or an event bus.

React/redux + bootstrap, make modal show unique for component

I have a component that shows a modal to pop up some content in my map. I have a pretty straight forward set up :
The JSX looks like this :
<Modal show={this.props.results.showPreviewModal} >
{myPreviewContent}
</Modal>
2 action-creators to open, close, and set the current item :
export function previewAsset(result) {
return {
currentResult: result,
type: actions.PREVIEW_ASSET
};
}
export function closePreviewModal() {
return {
type: actions.CLOSE_PREVIEW_MODAL
};
}
And their reducers :
case actions.PREVIEW_ASSET:
return state.set('currentPreview', action.currentResult).set('showPreviewModal', true);
case actions.CLOSE_PREVIEW_MODAL:
return state.set('showPreviewModal', false);
Now, this seems to work fine. However, the issue is that the component that has the modal inside of it is inside a map, as it is a singular search result (each result component has a some functionality so it is it's own component that is mapped over with results). The issue is that if I have 10 results, this modal opens 10 times when I click the button that fires the previewAsset action.
This makes sense, because the showPreviewModal is accessible by all components, but what I am wondering is if there is a way to make then unique for each component individually, so only the 1 modal opens, not all 10. Unsure how to approach this within react/redux, would very much appreciate any advice, thanks!
An approach I've used successfully is to pull the Modal component out of the loop (or map() in this case), and have a reducer for currentItem or something similar, which gets set when an item is selected (you could also use currentItemIndex, and then select the current item based on that in your connect() call).
In the parent component, you'd have the Modal as a child, and only display it if that currentItem is not null.
Here's a quick JSBin example to show you what I mean:
http://jsbin.com/fefoxoy/edit?html,js,console,output

Resources