conditional axios call for toggling state with Vue - javascript

I have a pretty simple method/function that I'm calling in Vue upon button click, which changes state (also toggles text on the button).
pauseTask: function() {
this.isOpen = !this.isOpen;
this.pauseButton.text = this.isOpen ? 'Pause' : 'Resume';
},
It works perfectly, but I need to make an axios call each time based on the state so if this.isOpen then I want to call:
axios.post('/item/status/pause',data)
.then((response) => {
// handle success
console.log(response.data);
if (response.data.success == false) {
this.errors = [];
const errorLog = Object.entries(response.data.errors);
for (var i = errorLog.length - 1; i >= 0; i--) {
console.log(errorLog[i][1][0]);
this.errors.push(errorLog[i][1][0]);
}
}
});
and if !this.isOpen then:
axios.post('/item/status/resume',data)
.then((response) => {
// handle success
console.log(response.data);
if (response.data.success == false) {
this.errors = [];
const errorLog = Object.entries(response.data.errors);
for (var i = errorLog.length - 1; i >= 0; i--) {
console.log(errorLog[i][1][0]);
this.errors.push(errorLog[i][1][0]);
}
}
});
How exactly can I achieve this with the current structure?

Id make a seperate js ( or ts ) file for talking to you API and put those calls into it, then import it as a 'itemService' or something
So from your "pauseTask" you could then do
if(this.isOpen) { itemService.pause(item) } else {itemService.resume(item)}
or you can trigger it on a watch for isOpen
watch: {
isOpen: function (val) {
if(val) { itemService.pause(item) } else {itemService.resume(item)}
}
the advantage of the watch is that anything that manipulates isOpen will trigger the calls.

Related

How do I add a method to a PASSWORD CLASS That checks for Validity

In Javascript, how to add method to a password class that checks for validity.
how to add method to a password class that checks for validity in javascript.
I am not completely sure about the requirement, but perhaps below would help
class Password{
constructor(passString){
this.passString = passString;
}
checkLength = () => {
return this.passString.lenght>8;
}
checkSpecialChars = () => { // TODO Need to implement
return true;
}
checkUpperChar = () => { // TODO Need to implement
return true;
}
checkLowerChar = () => { // TODO Need to implement
return true;
}
isValid = () => {
return this.checkLength() && this.checkSpecialChars() && this.checkLowerChar() && this.checkUpperChar();
}
}
let pass = new Password("ANUBHAV");
console.log(pass.isValid());

some directions/hints with a coding challenge in JS

Ive got a challenge to submit (no automated test/test cases- just a wrriten question) - and I'm not sure I'm doing right (being a noob and all that jazz).
I need to write classes and data structures for a call-center:
It has 3 levels of employees that can take the call;
For each incoming call the system will check who's available- starting at the lowest of the 3 employee levels,
then going up if no employee at that level is free to take the call- till it reaches the 3rd level.
they didn't give me any other instructions so I'm trying to do my best.
That's the code i have so far- what did I miss/should be changed?
class CallCenter{
constructor(){
if (!CallCenter.instance){
CallCenter.instance = this
this.callsQueue = []
this.employees = []
return this
}
return CallCenter.instance
}
addEmployee(emp){
this.employees.push(emp)
}
addPhoneCall(call){
this.callsQueue.push(call)
}
dispatchCallDirector(call){
const emp = this.employees.find(e => e.type === "director" && e.available)
}
dispatchCallManager(call){
const emp = this.employees.find(e => e.type === "manager" && e.available)
if (emp){
emp.getPhoneCall(call, (res) => {
if (!res){
this.dispatchCallDirector(call)
}
})
}
}
dispatchCall(){
const call = this.callsQueue[0]
this.callsQueue.splice(0, 1)
const emp = this.employees.find(e => e.type === "respondent" && e.available)
if (emp){
emp.getPhoneCall(call, (res) => {
if (!res){
this.dispatchCallManager(call)
}
})
}
}
}
module.exports = CallCenter
class Employee{
constructor(type){
this.available = true
this.type = type
}
set isAvailable(flag){ //available = true or false
this.available = flag
}
get isAvailable() {this.available}
getPhoneCall(call, report){
//if employee cant handle the call -
report(null)
//if employee can handle the call - this.available = false
}
}
module.exports = Employee

React Hook returning base values in useEffect

I ran into a roadblock when trying to update a hook when the web socket is called with new information and noticed that the hooks are returning the default values I set them to inside my useEffect, whilst inside the render it is returning the correct values. I am completely stumped and unsure why and was curious as to if anyone could help, much appreciated.
const [view, setView] = useState(false)
const [curFlip, setFlip] = useState(null)
tradeSocket.addEventListener('message', async (msg) => {
const message = JSON.parse(msg.data)
if (message.tradelink) {
// not needed
} else if (message.redItems || message.blueItems) {
// not needed
} else if (message.flips) {
console.log('effect ', view, curFlip) // this is where the issue occurs, it returns false and null
if (view && curFlip) {
console.log('theyre viewing a flip')
for (let i = 0; i < message.flips.length; i++) {
console.log('looping ' + i, message.flips[i].offer)
if (message.flips[i].offer === curFlip.offer) {
setFlip(message.flips[i])
}
}
}
setCoinflips(message.flips)
} else if (message.tradeid) {
// not needed
}
})
Image of what values it returns per render / effect called.
Based on our output, it seems that you set up the socket listener only once on initial render in useEffect.
Now since the useEffect callback is run once, the values used from closure inside the listener function will always show the initial valued
The solution here is to add view and curFlip to dependency array of useEffect and close the socket in useEffect cleanup function
useEffect(() => {
tradeSocket.addEventListener('message', async (msg) => {
const message = JSON.parse(msg.data)
if (message.tradelink) {
// not needed
} else if (message.redItems || message.blueItems) {
// not needed
} else if (message.flips) {
console.log('effect ', view, curFlip) // this is where the issue occurs, it returns false and null
if (view && curFlip) {
console.log('theyre viewing a flip')
for (let i = 0; i < message.flips.length; i++) {
console.log('looping ' + i, message.flips[i].offer)
if (message.flips[i].offer === curFlip.offer) {
setFlip(message.flips[i])
}
}
}
setCoinflips(message.flips)
} else if (message.tradeid) {
// not needed
}
})
return () => {
tradeSocket.close();
}
}
}, [curFlip, view]);

Console log message fires despite of the condition statement - Vue2

Purpose of my code, is to fire fetchNumbers() (that fetches numbers from API) when a user scrolls bottom of the page, some kind of infinite scroll. I'm having issue with condition inside axios promise (then), because it fires two console.log outputs at the same time. Seems like condition is ignored at all.
Method i'm using:
methods: {
fetchNumbers (type = 'default', offset = 0, limit = 0) {
return axios.get(globalConfig.NUMBERS_URL)
.then((resp) => {
if (type === 'infinite') {
console.log('infinite fired')
} else {
console.log('default fired')
}
})
}
Mounted function (where i suspect the issue):
mounted () {
window.onscroll = () => {
let bottomOfWindow = document.documentElement.scrollTop + window.innerHeight > document.documentElement.offsetHeight - 1
if (bottomOfWindow) {
this.fetchNumbers('infinite')
}
}
}
When i reload the page, or enter it, i'm getting 2 console outputs at the same time:
default fired
infinite fired
Sometimes the order is reversed.
UPDATE.
Methods that calling fetchNumbers()
async created () {
await this.fetchNumbers()
}
showCats (bool) {
this.showCategories = bool
if (!bool) {
this.category = [1]
} else {
this.category = []
}
this.isActive = true
this.fetchNumbers()
}
UPDATE 2.
Found the culprit - would post it in an answer.
UPDATE 3.
Issue is indeed with onscroll function. I have 3 pages in my APP: main page, numbers page, contact page. If i go to the numbers page (where onscroll function is mounted), then go to main or contact page, then this onscroll function is still attached and when i reach the bottom - it fires my api call, even if it's not the numbers page. Is it possible to limit this function only to numbers page?
I had to disable onscroll listener on destroy:
destroyed () {
window.onscroll = null
}
So when i visit the main or contact page, that listener won't be attached.
Also i had to move onscroll listener from mounted to created, because when it was in mounted () it was firing twice:
created () {
window.onscroll = () => {
let bottomOfWindow = document.documentElement.scrollTop + window.innerHeight > document.documentElement.offsetHeight - 1
if (bottomOfWindow) {
this.isActive = true
this.fetchNumbers('infinite', counter++ * this.limit)
}
}
}
fetchNumbers is most definetly called twice.
Try log every context as type.
fetchNumbers (type = 'default', offset = 0, limit = 0) {
return axios.get(globalConfig.NUMBERS_URL)
.then((resp) => {
if (type === 'infinite') {
console.log(type,'infinite fired'); //this will always print 'infinite', 'inifinite fired'
} else {
console.log(type,'default fired'); //this will print the caller's name and 'default fired'
type = 'default'; //after logging reset type to 'default' to continue the execution
}
})
}
async created () {
await this.fetchNumbers('created');
}
showCats (bool) {
this.showCategories = bool
if (!bool) {
this.category = [1];
} else {
this.category = [];
}
this.isActive = true
this.fetchNumbers('showCats');
}
Either created or showCats is being fired for some reason at the same time as window.onscroll. The randomly changing order suggests a race condition between the two methods.
UPDATE
This should work, provided you nested the desired page in a div with id="number_page_div_id" (you may probably have to adjust that elements height and position):
created () {
let element = getElementById('numbers_page_div_id');
element.onscroll = () => {
let bottomOfWindow = element.scrollTop + window.innerHeight > element.offsetHeight - 1;
if (bottomOfWindow) {
this.fetchNumbers('infinite')
}
}
}
you may approach separate condition instead of if/else e.g.
.then((resp) => {
if (type === 'infinite') {
console.log('infinite fired')
}
if (type === 'default '){
console.log('default fired')
}
})

react set component props programaytically

I am trying to set an react (v15) component its props callback function dynamically somehow. Something like below, bud it isn't working as I wanted it to be.
The whole idea behind this is that the popup needs to return specific data for an grid item that is pressed specifically in the grid (html table).
Any suggestions how to archive this dynamic setting of a component and its props?
The code below gives this error:
TypeError: can't define property "dynamicCallback": Object is not extensible
(I guess the element props is set with Object.preventExtensions)
getGridColumnData() {
var notificationsColumnsObj = columns.GridData; // from json file, Array With columns
for (let iColumn = 0; iColumn < notificationsColumnsObj.length; iColumn++) {
if (notificationsColumnsObj[iColumn].field === 'Landlord_Name') {
notificationsColumnsObj[iColumn]['editor'] = function (container, options) {
that.refs.searchCompanyPopup.props.dynamicCallback = function (data) {
var landlordName = null;
var landlordCode = null;
if (data) {
landlordCode = data.Code;
landlordName = data.Name;
}
options.model.set('Landlord_Code', landlordCode);
options.model.set('Landlord_Name', landlordCode);
};
};
}
}
return notificationsColumnsObj;
}
<SearchPopup ref="searchPopup" data={this.state.data} />
-
Update
How I managed to tet it working in the end. I used the state to set the function used for the callback by the popup. When you click an item in the grid: notificationsColumnsObj[iColumn]['editor'] is called, then the state is set for the popup callback when it finishes to call the function.
var that;
class TheComponent extends React.Component {
constructor(props,context) {
super(props,context);
this.state={
data: {},
landlordSelectedCallback: function (data) {},
}
that = this;
}
getGridColumnData() {
var notificationsColumnsObj = columns.GridData; // from json file, Array With columns
for (let iColumn = 0; iColumn < notificationsColumnsObj.length; iColumn++) {
//only one item will match this, not multiple
if (notificationsColumnsObj[iColumn].field === 'Landlord_Name') {
notificationsColumnsObj[iColumn]['editor'] = function (container, options) {
that.setState({
landlordSelectedCallback: function (data) {
var landlordName = null;
var landlordCode = null;
if (data) {
landlordCode = data.Code;
landlordName = data.Name;
}
options.model.set('Landlord_Code', landlordCode);
options.model.set('Landlord_Name', landlordCode);
}
}, () => { //callback function, after the state is set
$(ReactDOM.findDOMNode(that.refs.searchPopup)).modal(); //shows the <SearchPopup modal
$(ReactDOM.findDOMNode(that.refs.searchPopup)).off('hide.bs.modal');
$(ReactDOM.findDOMNode(that.refs.searchPopup)).on('hide.bs.modal', function (e) {
$(ReactDOM.findDOMNode(that.refs.searchPopup)).off('hide.bs.modal');
that.closeGridCellFromEditing(); //closes the grid cell edit mode
});
});
};
}
}
return notificationsColumnsObj;
}
render() {
return (<div>[other nodes]
<SearchPopup ref="searchPopup" data={this.state.data} onModalFinished={this.state.landlordSelectedCallback} />
</div>);
}
}
It's not working for two reasons:
Because your ref is called searchPopup, not props. Per the documentation for legacy string refs, you would access that via this.refs.searchProps.
Because props are read-only.
I'm a bit surprised that the second rule is actively enforced, but that's a good thing. :-)
If you want to change the props of a child component, you do so by changing your state such that you re-render the child with the new props. This is part of React's Lifting State Up / Data Flows Down philosophy(ies).
Rather than feeding a new callback function, just keep one function but feed data to it.
getGridColumnData() {
var notificationsColumnsObj = columns.GridData; //from json file, Array With columns
for (let iColumn = 0; iColumn < notificationsColumnsObj.length; iColumn++) {
if (notificationsColumnsObj[iColumn].field === 'Landlord_Name') {
notificationsColumnsObj[iColumn]['editor'] = (function (container, options) {
this.options = options
}).bind(this);
}
}
return notificationsColumnsObj;
}
dynamicCallback = function (data) {
var landlordName = null;
var landlordCode = null;
if (data) {
landlordCode = data.Code;
landlordName = data.Name;
}
this.options.model.set('Landlord_Code', landlordCode);
this.options.model.set('Landlord_Name', landlordCode);
}
render() {
return <SearchPopup ref="searchPopup" data={this.state.data} dynamicCallback = {this.dynamicCallback.bind(this)}/>
}

Categories

Resources