How to append additional text when making a POST request? - vuejs2

I got a Vue app with an input text field in a form where the user can type a new name for a branch. The user can also click a checkbox to designate whether a branch is active or inactive. Then, he submits the form via a submit button which then sends a POST (or PUT if he is editing the existing data) request to a remote data API.
Demo screenshot:
My question: I need to append the text (inactive) to the branch name when it is submitted to the server if the active checkbox is not selected, but also need to remove that inactive text if it exists and the active checkbox is left unchecked:
Hypothetical branch name with inactive flag and checkbox not checked:
ABCD (inactive)
Hypothetical branch name if active checkbox checked:
ABCD
Here is sample code for my POST method:
onSubmitAdd() {
this.loading = true
ApiService.postBranch(this.branch)
.then(() => {
this.loading = false
this.$router.push({ path: '/branches' })
})
.catch(err => {
if (err.response) {
this.errors = err.response.data
} else {
if (err.request) {
this.errors = err.request
} else {
this.errors = err.message
}
}
this.loading = false
console.error('Error from post', err)
})
}
Thanks for any tips you can provide for the logic to make this happen!

Add a v-model with your checkbox and based on that input you can decide whether to add or not the inactive text in your onSubmitAdd function

The conditional text is not appended when sending the post request. You have already set the state to be active or inactive (and of course your Api is expecting to read a boolean value e.g "branchStatus": boolean).
You set the conditional when you are retrieving the information with a get request which will return JSON data that should contain the state. You can then set the display text based on the state.
let displayStatus = ''
response.branchStatus ? displayStatus = "active" : displayStatus = "inactive"

Related

Is it okay to modify some state in Redux if after we modify it we call an action to overwrite the old state?

OK, say I have an initial state in our Redux store that looks like this:
const initialState = {
userReports: [],
activeReport: null,
}
userReports is a list of reports. activeReport is one of those reports (the one that is actively being worked with).
I want the active report to point to one in the array. In other words, if I modify the active report, it would modify one in the userReports array. This means, the two objects must point to the same memory space. That's easy to set up.
The alternative to this approach would be to copy one of the reports that is in the userReports array and set it as the active report (now it has a different memory address). The problem is now, when I edit the activeReport, I also have to search through the array of userReports, find the report that resembles the active report and modify it there too. This feels verbose.
Here is the question:
Would it be bad practice to have the activeReport point to a report in the array (same object). When I want to change the report I could do something like this (example is using redux thunk):
export const updateReport = (report) => async (dispatch, getState) => {
try {
const report = getState().reports.activeReport
// modify the active report here
report.title = "blah blah blah"
dispatch({ type: ACTIONS.UPDATE_REPORT, payload: report })
} catch (error) {
console.log(`ERROR: ${error.message}`)
}
}
And in my reducer:
case ACTIONS.UPDATE_REPORT:
return { ...state, activeReport: action.payload }
as you can see, after updating the report I still return a "new version" of that report and set it as active, but this approach also updates the report in the userReports array because they point to the same memory address.
I would say thats not ideal, do the reports have id's? If they do I would rather hold the userReports in an object with keys being the id's, then active report can just be an id and renamed to activeReportId so you can fetch the activeReport with userReports[activeReportId]
You also asked for reasons:
So firstly any screen that looks at userReports wont rerender because the reports aren't being reassigned.
Secondly if someone later wants to update those screens they will reassign userReports which could cause problems.
Thirdly its an unusual pattern which is a huge no no for redux. The point of redux is that it has a very obvious pattern so when you add things to it you don't have to think and can just make changes with confidence.
Your activeReport should not be pointing to an object in the userReports array, but rather it should be an id of the report, which the user is currently working on. Each of the report in the userReports will have a unique id field to identify the report - this would be helpful when rendering in react - this id field can be used as key.
Then your action creator/dispatcher will look like this:
export const updateReport = (updatedReport) => async (dispatch, getState) => {
dispatch({ type: ACTIONS.UPDATE_REPORT, payload: updatedReport });
}
You will call this on change in your component:
const onTitleChangeHandler = (e) => {
var newTitle = e.target.value;
// you will get the userReports and activeReport from props or by using some redux selector, also you will need to get dispatch and getState from redux
var activeReportObj = userReports.filter((r) => r.id === activeReport)[0];
updateReport({ title: newTitle, ...activeReportObj })(dispatch, getState);
}
Lastly, your reducer will be:
case ACTIONS.UPDATE_REPORT:
var newUserReports = state.userReports.map((r) => {
if (r.id === state.activeReport) {
return action.payload;
}
return r;
});
return { newUserReports, ...state };

wants to null values after api response is true

i want to clear my all text field when i post data to server and response become true here is my code of function where i post my data to API and its response exactly as i want but i want when response true all text field are clear..
updateProfile(){
axios.post( "http://172.104.217.178/api/update_sponsor_profile/"+this.state.UserId,{
name:this.state.name,
username:this.state.username,
address:this.state.address,
country_id:this.state.getCountryId,
state_id:this.state.getStateId,
city_id:this.state.getCityid,
} )
.then(response => {
alert(JSON.stringify(response));
if(response.data.status===1){
this.setState({name:null,username:null,address:null,getCountryId:null,getStateId:null,getCityid:null})
}
})
.catch(error => alert(error.response.data));
}
here is the code of my text fields
updateValue(text,field){
if(field==='name'){
this.setState({name:text})
}
else if(field==='username'){
this.setState({username:text})
}
else if(field==='address'){
this.setState({address:text})
}
}
While you may clear your state correctly the input field doesn't take its value from your state, it just updates it when you input something so clearing the state doesn't affect it at all. Try setting the Input field like this:
<Input
onChangeText={(text) => this.updateValue(text,'address')}
value={this.state.address}
/>
the value prop is inheritted from the native TextInput, its documentation is here.

Vue.js - Element UI - How to know the state of form validation

I'm using, vue-js and element-ui
I would like to check the state of the validation of a form without having to click on a submit button
Example
https://jsfiddle.net/nw8mw1s2/
Steps to reproduce
Click on each field
The verification is triggered with the blur
Start filling the different inputs
Question
How can I do so when the last input is validated, isFormValidated turns to true.
In other words, how can I say "If there is no field with the state error, then turn valudateState to true"
Tips
I guess we can check the validateState of each formItem of the form. But I do not see how to do it concretely.
I would create a new method (say updateIsFormValidated), and bind it to the native focusout event of the form:
<el-form :model="ruleForm2" #focusout.native="updateIsFormValidated" ...>
This method will fire each time any of the inputs in the form loses focus. It will attempt to check that each field in the form component has successfully been validated, firing each 100 milliseconds if the validation status of any of the form items is still pending:
updateIsFormValidated() {
let fields = this.$refs.ruleForm2.fields;
if (fields.find((f) => f.validateState === 'validating')) {
setTimeout(() => { this.updateIsFormValidated() }, 100);
} else {
this.isFormValidated = fields.reduce((acc, f) => {
let valid = (f.isRequired && f.validateState === 'success');
let notErroring = (!f.isRequired && f.validateState !== 'error');
return acc && (valid || notErroring);
}, true);
}
}
Here's a working fiddle.

Dojo: Select of empty value for FilteringSelect while required=false

Please look on this code:
dojo.require('dijit.form.FilteringSelect');
dojo.require('dojo.store.JsonRest');
dojo.declare('JsonFilteringSelect', dijit.form.FilteringSelect, {
constructor: function (options) {
dojo.declare.safeMixin(this, options);
if (this.url) {
this.store = new dojo.store.JsonRest({
target: this.url
});
} else {
console.log('JsonFilteringSelect: options.url is not defined');
}
}
});
var getPersonJsonFilteringSelect = new JsonFilteringSelect({
url: '/person/get',
name: 'Test',
title: 'Test title',
required: false,
autoComplete:false,
value: '',
pageSize:10,
queryExpr:'${0}'
}, dojo.byId('select'));
getPersonJsonFilteringSelect.startup();
});
Use case: Suppose I have 20 results into my FilteringSelect.
User selects 1 value of FilteringSelect.
This value set as value of
FilteringSelect.
But after user decides to change this value on
empty value.
As I understand, because required:false FilteringSelect should allow
to set empty value, but it is not. I observe this behavior here:
User clicks FilteringSelect textbox
User clears it
While user presses "Tab" or clicks by other element - FilteringSelect automatically selects first value.
How could I allow user to set empty value into FilteringSelect?
You should add an empty entry ("" or null maybe? I know "" works) to your data store after it's loaded (I'd put it at the beginning) but before startup of the widget.
The "required" issue is strange with FilteringSelect because it won't let you select any arbitrary value -- it has to be an entry from the data store. Yet, if it's not required shouldn't it not care?... Dojo is strange sometimes.

Set Value on dijit/form/FilteringSelect after its already been created

I have FilteringSelect using a MemoryStore. When a user types a value that is not in the store, they are prompted, asking if they would like to add the new value to the store.
If they do, we call the server, create the new item, and on the response, we publish an event.
The topic subscriber is notified that a new item was created and added to the MemoryStore, which adds the option to the filteringselect.
At this point, the filtering select still has the same displayValue, and the option exists in the select. FilteringSelect.get("value") still returns "".
If you were to type a space, then hit backspace, (ending up with the same value), FilteringSelect.get("value") would return the correct item id.
FilteringSelect.set("value", data[0].id) doesn't do anything, no exception thrown, no affect.
Here's the code, contains some of the random calls I tried.
require(["dojo/store/Memory", "dojo/_base/array", "dojo/topic"],
lang.hitch(this, function(Memory, array, topic) {
this.liftStore = new Memory({
data: []
});
array.forEach(data, lang.hitch(this, function(entry, i) {
this.liftStore.data.push({
name: entry.Name,
id: entry.ID,
identifier: entry.ID
});
}));
this.lift.set("store", this.liftStore);
topic.subscribe("LiftLog/NewLift", lang.hitch(this, function(data) {
debugger;
data[0].selected = true;
data[0].identifier = data[0].id;
this.liftStore.data.push(data[0]);
this.lift.reset();
this.lift.set("value", data[0].id);
this.lift.set("value", data[0].id.toString());
}));
}));
Have you tried setting the item (i.e. filteringSelect.set("item", newItem) instead of setting the value? Note that you should give it the whole item, not just the id or the displayed value.
So, push the item into the store, and then set the item on the FilteringSelect:
this.liftStore.data.push(newItem);
this.lift.set("item", newItem);