I want to change the credentials of state in a separate Javascript file which is a function() called LoginConfirmation.js. The credentials are in a class called login.js:
state = {
credentials: {
username: '',
password: '',
collapseID: '',
logged_in: true,
usernameChecked: LoginConfirmation.usernameChecked,
passwordChecked: LoginConfirmation.passwordChecked
},
isLoginView: true,
userAccount: []
}
I am trying to change the values of usernameChecked and passwordChecked inside LoginConfirmation.js without using any HTML onChange or onClick etc.
I am mapping through my database using:
{props.userAccount.map(userAccount => { ...
And then setting:
let usernameChecked = userAccount.username
Is it possible to set this usernameChecked value to usernameChecked in the credentials in login.js
It's hard to say without seeing the entire set up.
But I guess you could add a public method to the class in login.js that makes the changes you want, something like (assuming it's a React class component, not a js class):
updateUsernameChecked = (newValue) => {
this.setState(state => state.credentials.usernameChecked = newValue);
}
then pass the method to LoginConfirmation.js and call it with the new value.
Hope this helps.
Related
I am trying to use vuex-persist on nuxt.js but when try to read the data in a v-if doesn't work.
I created a new file inside plugins called vuex-persis.js with the following code:
import VuexPersistence from 'vuex-persist'
export default ({ store }) => {
new VuexPersistence({
storage: window.localStorage,
}).plugin(store);
}
and into nuxt.config.js I added the following code:
plugins: [{ src: '~/plugins/vuex-persist', mode: 'client' }],
The code that I use in order to store and get data is the following:
this.$store.commit('login', { idToken });
store.state.isLogin
and I have added the following file inside the project ./store/index.js
export const state = () => ({
isLogin: false,
idToken: '',
});
export const mutations = {
login(state, newState) {
state.isLogin = true;
state.idToken = newState.idToken;
},
logout(state) {
state.isLogin = false;
state.idToken = '';
},
};
I have the following navbar when I try to get the data from store:
navbar-button(to='/board', v-if='$store.state.isLogin')
p {{ $t("navbar_board") }}
navbar-button(v-if='$store.state.isLogin', #click.native='logout')
p {{ $t("navbar_logout") }}
but always enter in the same place, log in.
I tried to use a computed like this but doesn't work on the v-if
computed: {
isLogin: function () {
console.log(this.$store.state.isLogin);
return this.$store.state.isLogin;
},
},
the console.log prints the value stored in the browser but the console.log in node prints always the default state.
Anyway, the console.log always prints the correct value stored in the localstorage.
Any idea about how can I use that data in the v-if?
Thanks
Finally solved directly using $store.state.isLogin in the v-if
I have a login component which makes an API call with email and password to Ruby API and sets the isLoggedIn = true if the credentials are correct. When this is true, the navbar shows "logout" link and shows signin/signout when false. However, the issue is that it only works fine when page is not reloaded since I am not storing the session anywhere.
I am trying to set login state in local storage when the login is successful. It works fine in the login component, but doesn't when I try to read the local storage value in the other component. I assume this is because I am not storing it in shared state. Is it possible to store the value in state?
Login.js
axios
.post(apiUrl, {
user: {
email: email,
password: password,
},
})
.then((response) => {
if ((response.statusText = "ok")) {
setLoginStatus({ props.loginState.isLoggedIn: true });
localStorage.setItem('props.loginState.isLoggedIn', true);
console.log(response)
history.push("/");
}
})
App.js
let data = {
isLoggedIn: false,
user: {},
setSession:null
};
const [loginState, setLoginStatus] = useState(data);
const rememberMe = localStorage.getItem('loginState.isLoggedIn')
When I use console log the below either in App.js or Nav.js the value is null always.
localStorage.getItem('props.loginState.isLoggedIn');
The localStorage items as are saved as key value pairs. This is a string 'props.loginState.isLoggedIn', and will be access the same way from any component. Since you saved it with that key name it can only be accessed with that key name from any component.
Basic scenario -
I have an input element for e-mail address. On click of save, the e-mail is saved into the database. When I refresh, I want the saved value from database to show up as the initial value of the input. After that, I want to control the input's value through regular component state.
The problem I am having is setting the initial state value from props.
I thought I can set the state from props in CDU by making a prevProps to currentProps check.
Actual scenario -
The props I am trying to compare is an array of objects. So CDU shallow comparison won't help. How do I go about doing this?
Please note that I am not using or do not want to use any form library as I just have 3 input fields in my applications.
Thanks
You need to get data from the database on the component mount and set the state of your email. Like this below example (I am doing it on edit user) -
componentDidMount() {
var headers = {
"Content-Type": "application/json",
Authorization: `Token ${authToken}`
};
axios
.get(`${serverURL}users/${this.props.match.params.id}`, {
headers: headers
})
.then(res => {
//console.log(res.data);
let userdetails = res.data;
this.setState({
first_name: userdetails.first_name,
last_name: userdetails.last_name,
email: userdetails.email,
});
})
.catch(function(error) {
console.log(error);
});
}
Possible solution for this:
1. Create local state for email e.g
state = {
email: '';
}
dispatch the action in componentDidMount which will fetch the data and store it in redux state
use static getDerivedStateFromProps(props, state) to get updated values from props (ref. link :https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops) like
static getDerivedStateFromProps(nextProps, prevState) {
// do things with nextProps.email and prevState.email
return {
email: nextProps.someProp,
};
}
This is the method I'm using, pretty simple.
DailyCountTest: function (){
this.$store.dispatch("DailyCountAction")
let NewPatientTest = this.$store.getters.NewPatientCountGET
console.log(NewPatientTest)
}
The getter gets that data from a simple action that calls a django backend API.
I'm attempting to do some charting with the data so I need to assign them to variables. The only problem is I can't access the variables.
This is what the console looks like
And this is what it looks like expanded.
You can see the contents, but I also see empty brackets. Would anyone know how I could access those values? I've tried a bunch of map.(Object) examples and couldn't get any success with them.
Would anyone have any recommendation on how I can manipulate this array to get the contents?
Thanks!
Here is the Vuex path for the API data
Action:
DailyCountAction ({ commit }) {
axios({
method: "get",
url: "http://127.0.0.1:8000/MonthlyCountByDay/",
auth: {
username: "test",
password: "test"
}
}).then(response => {
commit('DailyCountMutation', response.data)
})
},
Mutation:
DailyCountMutation(state, DailyCount) {
const NewPatientMap = new Map(Object.entries(DailyCount));
NewPatientMap.forEach((value, key) => {
var NewPatientCycle = value['Current_Cycle_Date']
state.DailyCount.push(NewPatientCycle)
});
}
Getter:
NewPatientCountGET : state => {
return state.DailyCount
}
State:
DailyCount: []
This particular description of your problem caught my eye:
The getter gets that data from a simple action that calls a django backend API
That, to me, implies an asynchronous action and you might be getting a race condition. Would you be able to post a sample of your getter function to confirm my suspicion?
If that getter does indeed rely on an action to populate its contents, perhaps something to the effect of the following might do?
DailyCountTest: async () => {
await this.$store.dispatch('DailyCountAction')
await this.$store.dispatch('ActionThatPopulatesNewPatientCount')
let NewPatientTest = this.$store.getters.NewPatientCountGET
// ... do whatever with resulting array
}
You can also try with a computer property. You can import mapGetters
import { mapGetters } from 'vuex'
and later in computed properties:
computed: {
...mapGetters(['NewPatientCountGET'])
}
then you can use your NewPatientCountGET and it will update whenever the value changes in the store. (for example when the api returns a new value)
Hope that makes sense
Currently, I have a modal material dialog window that asks the user to input a number and then hit search. On search, it fetches data from api call and gets back a response object. I want to use the response object to populate a new page (edit form).
My question is, how can I past the data, particularly the number the user entered on the material dialog component to another component, so that it can fetch the api call results or how can I pass my response object to my edit from from dialog?
E.g.
Here's my search function:
search(searchNumber) {
if (this.selectedOption === 'Bill Number') {
this._transactionService.findExistingTransactionByBillNumber('U001', searchNumber)
.subscribe(data => this.transactionResponse = data);
console.log(JSON.stringify(this.transactionResponse));
this.router.navigate(['/edit-transaction-portal']);
} else {
this._transactionService.findExistingTransactionByTransactionNumber('U001', searchNumber)
.subscribe(data => this.transactionResponse = data);
console.log(JSON.stringify(this.transactionResponse));
this.router.navigate(['/edit-transaction-portal']);
}
}
I want to be able to either 1) pass the response object I get here or pass the searchNumber the user entered, so that I can do a lookup within my edit form component. I need to pass in either one from this component to my new component that I navigate to.
EDIT: Accepted solution shows how to add query params to this.router.navigate() and how to retrieve it by subscribing to activateRoute, a different approach than the one identified in the other SO post.
You can pass the number (bill/transaction)
this.router.navigate(['/edit-transaction-portal'], { queryParams: { bill: 'U001' } });
this.router.navigate(['/edit-transaction-portal'], { queryParams: { transaction: 'U001' } });
then in your component(edit-transaction-portal) hit the api to get the data. In component you should include ActivatedRoute in constructor. It will be something like:
isBill: boolean;
isTransaction: boolean;
number: string;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.sub = this.route
.queryParams
.subscribe(params => {
this.isBill = params['bill'] != undefined;
this.isTransaction = params['transaction'] != undefined;
this.number = this.isBill ? params['bill'] : params['transaction'];
// Call API here
});
}
My question is, how can I past the data, particularly the number the
user entered on the material dialog component to another component
You can pass it throw material dialog component. Inject dialogRef to you component which opened in the dialog:
constructor(
public dialogRef: MatDialogRef<SomeComponent>,
#Inject(MAT_DIALOG_DATA) public data: any,
) { }
After the submitting data, you can pass any data to component which opened this dialog, by closing the dialog:
onSubmit() {
this.service.postProduct(this.contract, this.product)
.subscribe(resp => {
this.dialogRef.close(resp);
});
}
And in your Parent component, who opened this dialog can get this passed data by subscribing to afterClosed() observable:
Parent.component.ts:
openDialog(id) {
const dialogRef = this.dialog.open(SomeComponent, {
data: { id: anyData}
});
dialogRef.afterClosed().subscribe(result => {
if (result) {
// do something...
}
});
}
Would I pass the data object in dialog.open()? How would I retrieve it
from there?
Look at openDialog() above. It has data property, that you can send to dialog components. And in the opened component inject MAT_DIALOG_DATA as this:
#Inject(MAT_DIALOG_DATA) public data: any,
to access passed data object as shown code above
Official docs[sharing-data-with-the-dialog-component]
if you want to pass data which the help of routing you have to define route which takes value as part of rout like as below
const appRoutes: Routes = [
{ path: 'hero/:id', component: HeroDetailComponent },];
it will from code side
gotoHeroes(hero: Hero) {
let heroId = hero ? hero.id : null;
// Pass along the hero id if available
// so that the HeroList component can select that hero.
// Include a junk 'foo' property for fun.
this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);
}
Read : https://angular.io/guide/router#router-imports
If you want to pass data between two component then there is #Input and #Output property concept in angular which allows you to pass data between components.
#Input() - this type of property allows you to pass data from parent to child component.
Output() - this type of property allows you to pass data from child to parent component.
Other way to do it is make use of Service as use the same instance of service between component.
Read : 3 ways to communicate between Angular components