Vue JS Event bus data not working outside scope of event - javascript

I am using event bus to show alert on update data.so whenever user update the data i want to show an alert showing "Data is udpated" so for that i am using event bus
here is BlogEdit.vue Component where i am firing event
app.$router.push('/', () => {
vueBus.$emit('showAlertBox')
})
And In BlogList.vue I am listning for this event
data: function(){
return {
showalert: false,
}
},
vueBus.$on('showAlertBox',(data) => {
this.showalert = true;
console.log(this.showalert); //Returns True
})
console.log(this.showalert); //Returns False
But the result is unexpected as it change back to false.
Why this.showalert changed to false ? So that cause to not showing alert box.
Since i am new to vue js i read the documenatation and other solutions but i cant figure out where am i going wrong with this.

Related

How do I pass data into a click() function when manually call it?

I have two buttons: #btn1 and #btn2. I have set up the following click event handlers:
$('#btn1').click(function(event){
// do something...
})
$('#btn2').click(function(event){
$('#btn1').click(); // works
$('#btn1').click({data:5}); // not firing at all
})
I have Googled but most of the posts are talking about how to display the data when a user really clicks. However, in my case, I am not clicking the #btn1 but just call the click() handler from another function.
Thanks for any help!
use .trigger():
$('#btn1').trigger('click', { data: 5 });
and then the handler should look like:
$('#btn1').click((event, data) => {
// data should be { data: 5 } here
})
https://api.jquery.com/trigger/
https://jsfiddle.net/hrcnskzm/

React useState isn't setting opposite boolean correctly

I have a simple button on page with onClick event, and then useState hook that is by default set to false. Then I have elements on page, when I click on them I wanna do an action, but only if the state of that useState hook is set to true, which is done by if condition, but for some reason it passes it, even though the state should be false. My code:
Initiating the hook:
const [ isEraser, setIsEraser ] = useState(false);
Setting state on button click:
<span
className="scroll"
onClick={() => {
setIsEraser((isEraser) => !isEraser);
}}
>
The condition:
console.log('Eraser is set to', isEraser);
if (isEraser == true) {
// Code
}
The output of the console.log:
no changing state (is default false) -> false
changing state to true -> true
changing state back to false and triggering that event in which the condition is -> false, true, false
Edit:
I can't pass full component code, because it's kinda big, and some parts of code are protect by client contract, but the condition is in onClick event:
$body.on('click', '.tvs-annotated-text, .tvs-annotate-element', function(
e
) {
console.log('Eraser is set to', isEraser);
if (isEraser === true) {
setIsAlert(1);
// Odstraníme vybranému elementu backround
this.style.backgroundColor = '';
this.classList.remove('tvs-annotated-text');
this.classList.remove('tvs-annotate-element');
}
});
pretty sure you just need to do setIsEraser(!isEraser)
You don't have to use a function to set state setIsEraser((isEraser) => !isEraser); → setIsEraser(!isEraser)
Allright, so the problem was that the onClick trigger was written in jQuery, after rewriting it to normal javascript it works now. Big thanks to you guys.
In the setIsEraser you need to pass the last state. you passed the initial state in it so every time you press the button it passes false as isEraser.
change the isEraser in setIsEraser function to something else like pre or previous, etc.
<span
className="scroll"
onClick={() => {
setIsEraser((pre) => !pre);
}}
>
In this way pre would be the last state not the initial state and your program will work just fine.

Using ag-grid with many rows and Autosave

I'm using ag-grid (javascript) to display a large amount of rows (about 3,000 or more) and allow the user to enter values and it should auto-save them as the user goes along. My current strategy is after detecting that a user makes a change to save the data for that row.
The problem I'm running into is detecting and getting the correct values after the user enters a value. The onCellKeyPress event doesn't get fired for Backaspace or Paste. However if I attach events directly to DOM fields to catch key presses, I don't know how to know what data the value is associated with. Can I use getDisplayedRowAtIndex or such to be able to reliably do this reliably? What is a good way to implement this?
EDIT: Additional detail
My current approach is to capture onCellEditingStopped and then getting the data from the event using event.data[event.column.colId]. Since I only get this event when the user moves to a different cell and not just if they finish typing I also handle the onCellKeyPress and get the data from event.event.target (since there is no event.data when handling this event). Here is where I run into a hard-to-reproduce problem that event.event.target is sometimes undefined.
I also looked at using forEachLeafNode method but it returns an error saying it isn't supported when using infinite row model. If I don't use infinite mode the load time is slow.
It looks like you can bind to the onCellKeyDown event. This is sometimes undefined because on first keydown the edit of agGrid will switch from the cell content to the cell editor. You can wrap this around to check if there is a cell value or cell textContent.
function onCellKeyDown(e) {
console.log('onCellKeyDown', e);
if(e.event.target.value) console.log(e.event.target.value)
else console.log(e.event.target.textContent)
}
See https://plnkr.co/edit/XhpVlMl7Jrr7QT4ftTAi?p=preview
As been pointed out in comments, onCellValueChanged might work, however
After a cell has been changed with default editing (i.e. not your own custom cell renderer), the cellValueChanged event is fired.
var gridOptions = {
rowData: null,
columnDefs: columnDefs,
defaultColDef: {
editable: true, // using default editor
width: 100
},
onCellEditingStarted: function(event) {
console.log('cellEditingStarted', event);
},
onCellEditingStopped: function(event) {
console.log('cellEditingStopped', event);
},
onCellValueChanged: function(event) {
console.log('cellValueChanged', event);
}
};
another option could be to craft your own editor and inject it into cells:
function MyCellEditor () {}
// gets called once before the renderer is used
MyCellEditor.prototype.init = function(params) {
this.eInput = document.createElement('input');
this.eInput.value = params.value;
console.log(params.charPress); // the string that started the edit, eg 'a' if letter a was pressed, or 'A' if shift + letter a
this.eInput.onkeypress = (e) => {console.log(e);} // check your keypress here
};
// gets called once when grid ready to insert the element
MyCellEditor.prototype.getGui = function() {
return this.eInput;
};
// focus and select can be done after the gui is attached
MyCellEditor.prototype.afterGuiAttached = function() {
this.eInput.focus();
this.eInput.select();
};
MyCellEditor.prototype.onKeyDown = (e) => console.log(e);
// returns the new value after editing
MyCellEditor.prototype.getValue = function() {
return this.eInput.value;
};
//// then, register it with your grid:
var gridOptions = {
rowData: null,
columnDefs: columnDefs,
components: {
myEditor: MyCellEditor,
},
defaultColDef: {
editable: true,
cellEditor: 'myEditor',
width: 100
},
onCellEditingStarted: function(event) {
console.log('cellEditingStarted', event);
},
onCellEditingStopped: function(event) {
console.log('cellEditingStopped', event);
}
};

React componentDidMount not called on component reload

I have a list of data table. In data table I have data w.r.t to some device Whenever I click ID I open a sidebar with some data displaying inside that.
The problem what I am facing is onclick of ID first time it calls the api gets the data and displays properly. But, after closing sidebar when I click again on ID it doesn't load anything (no calls for APIs).
I am not able to create code pen for that but below is my code.
My Code -
onCLick ID -
_onClickCompliance(deviceId);
const _onClickCompliance = deviceId => {
ReactDOM.render(
<ComplianceDetails deviceId={deviceId} />,
document.getElementById("ComplianceDetailsModalDiv")
);
};
Inside ComplianceDetails component - First time onClick it goes inside componentDidMount but on click again it's not. That's why I have componentDidUpdate for this. If I remove this componentDidUpdate, it always loads the old data in sidebar after onCLick of ID in table.
`getDetailsByDeviceID` this is called to get the data from API and sets value in state
My Code -
componentWillReceiveProps() {
this.setState({ sideBarShow: true });
}
componentDidMount = () => {
this.getDetailsByDeviceID();
};
componentDidUpdate(prevProps) {
if (this.props.deviceId !== prevProps.deviceId) {
this.getDetailsByDeviceID();
}
}
getDetailsByDeviceID code -
getDetailsByDeviceID = () => {
try {
this._getComplianceDetailsApi(); //apis
} catch (err) {
toast({
message: err,
flavor: "error",
options: { isHtml: true }
});
}
};
If I remove this it calls the page indefinitely.
if (this.props.deviceId !== prevProps.deviceId)
Do I have to call componentWillUnmount()? Please guide me.
Let me know If I am not clear. Thanks.
If you want your component to re-mount when deviceId change you can use the key prop on ComplianceDetails, like this :
<ComplianceDetails key={deviceId} deviceId={deviceId} />

SAPUI5 - Model.Remove generates two requests

I am currently facing a strange behavior with my SAPUI5 coding when I do a DELETE with the model (sap.ui.model.odata.v2.ODataModel). I wanted to implement a list, which displays some "Favorites" in a SelectDialog. By pressing the icon, the users can delete a favorite. For the item itself I used a FeedListItem, which is triggering the iconPress-Event _handleIconPressDelete.
<FeedListItem icon="sap-icon://delete" iconActive="true" iconPress="_handleIconPressDelete" text="{Name}" sender="{ID}"/>
The event looks like this:
_handleIconPressDelete: function(oEvent) {
var oModel = oEvent.getSource().getModel();
oModel.remove(oEvent.getSource().getBindingContext().getPath(), {
success: function(data) {
// success handling
},
error: function(e) {
// error handling
}
});
}
But when this event is triggered, two identical delete requests are generated and causing an error, because with the current changeset coding in the backend, I am only allowed to do one request at the same time.
The strange thing is, this behavior only appears when I open the dialog the first. When I close and reopen it, everything works fine.
Do you have any ideas, what I might do wrong here so that two requests are generated? I also checked, if the event is triggered multiple times, but that wasn't the case.
As current workaround I am using deferredGroups as shown in the snipped below so that the two request are separated, but I think there must be better ways to solve this.
_handleIconPressDelete: function(oEvent) {
var oModel = oEvent.getSource().getModel();
oModel.setDeferredGroups(["group1"]);
oModel.remove(oEvent.getSource().getBindingContext().getPath(), {
groupId: "group1",
success: function(data) {
// success handling
},
error: function(e) {
// error handling
}
});
oModel.submitChanges({
groupId: "group1"
});
}
I too experienced the same issue where the event associated with iconPress of FeedListItem triggers twice though user click only once..
Following is a workaround which you can implement using custom coding.
Declare the following variable in view controller's onInit()
this._bFirstTrigger = true;//SETTING FOR THE FIRIST TIME
Use this in FeedListItem's iconPress event to ensure that the relevant code executes only once as follows:
_handleIconPressDelete: function(oEvent) {
if (this._bFirstTrigger) {
var oModel = oEvent.getSource().getModel();oModel.setDeferredGroups(["group1"]);
oModel.remove(oEvent.getSource().getBindingContext().getPath(), {
groupId: "group1",
success: function(data) {
// success handling
},
error: function(e) {
// error handling
}
});
oModel.submitChanges({
groupId: "group1"
});
}
this._bFirstTrigger = false;
}
else{
this._bFirstTrigger = true;
}
Regards,
Fahad Hamsa

Categories