The html is not shown based on locally saved variables - javascript

I have a component that needs to display html based on a boolean variable. I make this variable the same as the one I set in the localStorage.
So if I click on foo, I set it to false both as a variable and in the localStorage. If I click on the bar I set it to true.
Now, before loading the component I'm going to get this variable, and I make it the same as the one I have locally, so if I clicked on foo, when I reload the component, the variable is false, and therefore the html should show me foo. but I don't understand why he shows me bars!!!
It's a bit complicated to explain I hope you understand from the code:
<template>
<div id="app">
<h2 v-if="!isTrue">FOO</h2>
<h2 v-else>BAR</h2>
<button #click="foo()">FOO</button>
<button #click="bar()">BAR</button>
</div>
</template>
<script>
export default {
name: 'App',
data: function () {
return {
isTrue: null,
};
},
created() {
const boh = localStorage.getItem('boh');
this.isTrue = boh;
console.log('boh', boh);
console.log('isTrue', this.isTrue);
},
methods: {
foo() {
this.isTrue = false;
localStorage.setItem('boh', false);
},
bar() {
this.isTrue = true;
localStorage.setItem('boh', true);
},
},
};
</script>
I am attaching an example on stackblitz so maybe you can do tests:
https://stackblitz.com/edit/vue-b3ieft?file=src%2FApp.vue

Because a variable you saved in the localStorage is a string. When you do:
const boh = localStorage.getItem('boh');
this.isTrue = boh;
Actually you get:
this.isTrue = 'true';
And this string is always true.
To avoid this you could check if it is true string:
const boh = localStorage.getItem('boh');
this.isTrue = boh === 'true';
https://stackblitz.com/edit/vue-mnuhbr?file=src%2FApp.vue

Adding on to #Georgy's answer. To escape an unnecessary check, it is a good practice for booleans to be stringified while setting the localstorage, and parsed when getting the item.
Setting
localStorage.setItem("boh", JSON.stringify(false));
Getting
const boh = JSON.parse(localStorage.getItem('boh'))

Related

Onclick & boolean switch

I have tried to make an function with a onclick that when you click it, it will change the value from 'suspended' in true (this is about suspending a website user account)
suspended = false;
type user = User['suspended'];
function blokkeerFunctie() {
// get user & user element
document.getElementById('userInfo') && document.getElementById('blokkeren');
// blocks user when clicked
if (document.getElementById('blokkeer')?.addEventListener('click', blokkeerFunctie)) {
type user = !User['suspended'];
} else {
// deblocks user when clicked
document.getElementById('deblokkeer')?.addEventListener('click', blokkeerFunctie);
type user = User['suspended'];
}
console.log('blokkeerFunctie');
}
blokkeerFunctie();
I thought with !User i will reverse the boolean value from false in true, but that code isn't even read. ▼
'user' is declared but never used.ts(6196)
You shouldn't put event listeners in your conditional if/else in this way. Here's how I would approach what you're trying to accomplish. You will need to add types to these variables, but you'll get the basic logic here.
let User = {
suspended: true
};
let button = document.querySelector('#suspender');
function setSuspendButton() {
button.innerText = User['suspended'] ? 'Unsuspend' : 'Suspend';
}
window.addEventListener('load', () => {
button.addEventListener('click', blokkeerFunctie)
setSuspendButton();
})
function blokkeerFunctie() {
User['suspended'] = !User['suspended'];
setSuspendButton();
}
<button id='suspender'></button>
type user = creates a new type, not a value. It's unused in each branch of the if because you just create a new type, named user which shadows the type of the same name from the parent scope, which is never used by anything.
Furthermore, this line does nothing:
document.getElementById('userInfo') && document.getElementById('blokkeren');
This line gets up to two references to DOM elements, but doesn't save them anywhere, or perform any logic on them.
I think you want something more like this?
const user = {
name: 'Joe',
suspended: false
}
function blokkeerFunctie() {
// block/deblocks user when clicked
if (document.getElementById('blokkeer')?.addEventListener('click', blokkeerFunctie)) {
user.suspended = !user.suspended // toggle `suspended` back and forth
}
console.log('blokkeerFunctie');
}
blokkeerFunctie();
Working example

Accidentally updating child variables

I'm currently working in a page with parent/child components. Somehow my child component gets updated when I manage its variables in the parent component.
What I'm trying to do:
My child component has a 'site' variable with all the data i need to send via API
My parent component has a Save button to send the child data to the Back-end
When 'site' changes in the child component, I'm emitting an event #change to the parent component
The #change event contains all the data I need, but not in the format I want
There is a function submit() that gets this data and modify the one of the arrays so that this: ['foo','bar'] becomes this 'foo,bar'
The problem when I do the step '5' my child component gets updated
The child component inside the parent component
<configuracoes :configuracoes="configuracoes" #change="setData"
v-if="currentPage === 'configs'"/>
The change event emitted by the child component
this.$emit("change", this.site);
The important part of 'site' var
site: {
seo: {
keywords: [],
...
},
...
},
The setData() function
setData(data) {
this.data = data;
},
The submitData() function
submitData() {
if (this.currentPage === "configs") {
let data = ({}, Object.assign(this.data))
let keywords = data.seo.keywords.join(',')
data.seo.keywords = keywords
this.$store.dispatch("sites/updateSite", {
empresa_id: this.user.empresa_id,
site_id: this.siteId,
dados: data,
});
}
}
As you can see, I'm declaring another variable let data to avoid updating this.site variable, but no success
First of all, there is an issue with how you're "copying" your this.data object.
let data = ({}, Object.assign(this.data)); // this doesn't work
console.log(data === this.data); // true
const dataCopy = Object.assign({}, this.data); // this works
console.log(dataCopy === this.data); // false
The way Object.assign works, all the properties will be copied over into the first argument. Since you only pass a single argument, it doesn't change and is still pointing to the same old object.
If you use the correct way, you will most likely still run into the same issue. The reason is that data.seo is not a primitive value (a number or a string), but is an object.
This means that the whole seo object will be copied over into the new copy. In other words, even though dataCopy !== this.data, dataCopy.seo === this.data.seo. This is known as "shallow copy".
You want to make sure you DO NOT modify the original seo object, here are a few ways to do that.
let goodCopy;
const newKeywords = this.data.seo.keywords.join(',');
// use object spread syntax
goodCopy = {
...this.data,
seo: {
...this.data.seo,
keywords: newKeywords,
},
};
// use Object.assign
goodCopy = Object.assign(
{},
this.data,
{
seo: Object.assign(
{},
this.data.seo,
{keywords: newKeywords}),
});
// create a copy of "seo", and then change it to your liking
const seoCopy = {...this.data.seo};
seoCopy.keywords = newKeywords;
goodCopy = Object.assign({}, this.data, {seo: seoCopy});
this.$store.dispatch('sites/updateSite', {
empresa_id: this.user.empresa_id,
site_id: this.siteId,
dados: goodCopy,
});
If you want to read up on ways to copy a JavaScript object, here's a good question.

knockoutobservable value update only inside the clicked function but not in the UI in Type Script code

please I am stuck in this problem from yesterday without fixing :
when I click the knockout checkbox, the button will send the true-false value and by the click, event reach the driverSelected function, there will print the item and it works perfect, but I need to filter the selected data with other information, but it not changes is empty
Html
<input type="checkbox" data-bind=" checked:isSelectedDriver , click:$root.driverSelected()" />
this.assignedDriver = ko.observable(new Model.Driver());
view model function
driverSelected = () => {
return (item, ui: any) => { // lambda expression
if (item.isSelectedDriver()) {
this.assignedDriver = ko.observable(item.driver);
this.assignedDriver.valueHasMutated;
console.log(this.assignedDriver());
return true
}
}
}
the result in HTML it shows me the default which empties without errors even when I delete the attribute value ( wbc_name) is show me [ object object }
You are reassigning what this.assignedDriver is, instead of setting the value in your JS.
To assign a value to an observable, you call the observable with the value that you want to set it to, for example:
this.thing = ko.observable(5); // Observable created, initial value 5.
this.thing(42); // Sets the value of the observable, value is now 42;
See the documentation that explains this.
In this case, the fix would be to modify the first two lines in the if-statement in driverSelected.
driverSelected = () => {
return (item, ui: any) => {
if (item.isSelectedDriver()) {
this.assignedDriver(item.driver);
console.log(this.assignedDriver());
return true;
}
};
};

Passing data property as function argument in vue.js

Instead of having few methods that look like:
showDiv1(){
this.showDiv1 = true
},
showDiv2(){
this.showDiv2 = true
}
I am trying to create one like:
showElements(...elementNames){
elementNames.forEach(name => {
this.$data.name = true
})
}
The idea was to pass one or few properties from data and when calling the method those elements would should up on screen.
In data I have something like this:
data() {
return {
div1 = false,
div2 = false
}
}
In html I tried to call the function on click in a couple of ways:
<button #click="showElements('div1')">Show<button>
<button #click="showElements(div1)">Show<button>
<div v-if="div1">
<p>Hello</p>
</div>
But nothing happens.
Seems like you have a syntax error. Instead of writing to your data object like this:
data() {
return {
div1 = false,
div2 = false
}
}
You should write it like this:
data() {
return {
div1: false,
div2: false
}
}
Make sure to only use syntax that fits an object in the data object. Then, you can call it like this:
<button #click="showElements(div1)">Show<button>
One more thing, when accessing the data you don't actually need to write $data. Simply write 'this.name' in order to access your data.
Dynamic property names are supposed to be accessed with bracket notation:
showElements(...elementNames){
elementNames.forEach(name => {
this[name] = true
})
}
The method is supposed to be used like:
<button #click="showElements('div1')">Show<button>

cannot modify nodejs module value

I want initialize a module with some default values and change them later if required. To do this I have a module/singleton which contains a _state value. I have exposed a setter method to update that value. However, the setter does not update the _state member variable. The code looks like this:
var StateObject = function () {
var _state = { a: 1 };
return {
state : _state,
setState : function (s) {
_state = s;
}
};
}();
modules.export = StateObject;
and the calling function:
var SO = require('./state-object');
console.log(SO.state.a); // prints 1
SO.setState({a: 2});
console.log(SO.state.a); // still prints 1
Can anyone explain what would cause this and if there is a work around?
The potential pitfall of a solution like this is if some piece of code stores SO.state locally and references that. If that happens and you call setState() some time later, the reference won't be updated in that piece of code. That's just something to be aware of when you replace the whole state and not just individual values in the state.
The problem here has to do with references. When you execute StateObject(), the state variable stores the initial reference to _state. Then when you call setState(), you overwrite _state, but state is still holding on to the previous reference.
You might try something like this:
modules.export = {
state: { a: 1 },
setState: function(v) {
this.state = v;
}
};
Well, the problem is with the reference not being updated, as mscdex mentioned.
In my opinion the main problem is actually your logic: why have a setter if you don't have a getter?
var SO = function () {
var _state = { a: 1 };
return {
getState : function () {
return _state;
},
setState : function (s) {
_state = s;
}
};
}();
console.log(SO.getState().a); // prints 1
SO.setState({a: 2});
console.log(SO.getState().a); // prints 2
This works, as it is also returning the reference to the latest set object. And this has actually nothing to do with node or modules, you can run your example in the browser's JavaScript console.

Categories