Am I accessing the DOM correctly in Vue.js? My task is such that when I click on the title, a form appears and I can edit the record in it. To cancel, press ESC, and to save, press ENTER.
my template:
<div v-for="(note, i) in notes" :key="i">
<div class="card-body">
<h5 class="card-title" #click="editNote($event, i)">{{note.title}}</h5>
<input type="hidden">
</div>
</div>
my script:
editNote (event, i){
let parent = event.target,
block = parent.closest('.card-body'),
input = block.querySelector('input'),
text = parent.textContent;
input.type = "text"
input.value = text
parent.style.display = "none"
input.onkeydown = (e) =>{
if (e.keyCode == 27){
input.type = "hidden"
parent.style.display = "block"
}
else if (e.keyCode == 13){
input.type = "hidden"
parent.style.display = "block"
parent.textContent = input.value
this.notes[i].title = input.value
}
}
}
Your solution is a solution, but you can do much better by using v-if, v-model and #keypress.
With v-if you can check whether a specific variable is true or not. With that you can manipulate your h5 and input by setting the variable in editNote to true. This is how you can get rid of the display CSS manipulation.
With #keypress in the input tag, you can get rid of the keydown event and enter your solution there.
With the v-model you can easily get the value whenever someone enters something in the input. Also, you can get directly the value of the input.
Checkout these links for more:
v-model
v-if
event handling
Related
I am trying to make a quiz game and after getting the answers to shuffle around, they sometimes are surrounded by "\" \"" marks. When just displaying the correct answer, it will not have these marks. I have tried using v-html which normally gets rid of this issue, however then all the answers are [Object object]. I have tried trying to retrieve just part of the arrays and objects with [0] [2] and so one but that didn't work either.
Here is my html:
Style binded so that if that button is selected, the background colour of the button will change. Colour is a variable changed when answer is checked -->
<button class="answer" :disabled="answered" #click="checkAnswer(shuffled[0])" :style="selected == shuffled[0].value && {backgroundColor: colour}">{{shuffled[0]}}</button>
<button class="answer" :disabled="answered" #click="checkAnswer(shuffled[1])" :style="selected == shuffled[1].value && {backgroundColor: colour}">{{shuffled[1]}}</button>
<button class="answer" :disabled="answered" #click="checkAnswer(shuffled[2])" :style="selected == shuffled[2].value && {backgroundColor: colour}">{{shuffled[2]}}</button>
<button class="answer" :disabled="answered" #click="checkAnswer(shuffled[3])" :style="selected == shuffled[3].value && {backgroundColor: colour}">{{shuffled[3]}}</button>
<!-- Button running function to end game with parameters of current correctCount and totalQuestions -->
<button type="button" #click="finish(correctCount, totalQuestions)" class="btn button done">Finish</button> <div class="correct"><p v-if="answered"><strong>Correct Answer:</strong> {{correctAnswer}}</p></div><button type="button" :disabled="!nextAvailable" #click="getQ(selectedDifficulty)" #click="shuffle(options)" class="btn button next">Next</button>
<!-- Button which is disabled when a question loads and runs functions to shuffle the answers and get a new question -->
</div>
<h3>Debugging</h3>
<p><strong>Correct Answer: </strong>{{correctAnswer}}</p>
</div>
And here is my relevant JS:
let getQ = async function() {
let response = await fetchURL('https://the-trivia-api.com/api/questions?categories=film_and_tv&limit=1®ion=AU'); // api source link
this.correctAnswer = response[0].correctAnswer;
this.incorrectAnswerOne = response[0].incorrectAnswers[0];
this.incorrectAnswerTwo = response[0].incorrectAnswers[1];
this.incorrectAnswerThree = response[0].incorrectAnswers[2];
this.question = response[0].question;
this.shuffle(options); // shuffles the answers in options variable
this.answered = false; // resets the disabled buttons
this.nextAvailable = false; // disables 'next' button
this.totalQuestions++; // increases number of total questions
}
// function to shuffle the answers
let shuffle = function(array) {
this.selected = null; // resets selected variable
let num = array.length, t, raInt;
// while there are remaining elements to shuffle
while (num) {
// choose random
raInt = Math.floor(Math.random() * num--);
// swap with current element
t = array[num]
array[num] = array[raInt];
array[raInt] = t;
}
this.shuffled = array.value; // saves to shuffled variable
}
All variables are declared and returned in the component. What I want is for it to always have every answer shuffled and without these markings.
There are some error messages but I am not quite sure what they mean:
If I haven't provided enough information or code, please feel free to say if you need more.
Using Bootstrap-Vue (vue2).
When clicking on a div, I need to show a tooltip only if isDisabled=true
<div id="disabled-wrapper" class="includeExclude" :class="{ disabled: isDisabled }"
#click="excludeCountry" tabindex="0">
<b-tooltip v-if="isDisabled" variant="secondary" target="disabled-wrapper" triggers="click">
</b-tooltip>
this is the method that fires on clicking the div
excludeCountry(){
if (this.temporaryFilters['countries'] != undefined){
this.isDisabled = true;
}
else {
this.operator = 'notin';
this.exclude = !this.exclude;
}
}
I cannot get the v-if condition to work, If I remove it, the tooltip works fine clicking on the element
the part
if (this.temporaryFilters['countries'] != undefined){
this.isDisabled = true;
}
works because I have some logs on this.isDisabled and it changes to true
this.temporaryFilters['countries'] !== undefined
You can update the condition like this and try.
If condition works and this.isDisabled is true, you can see tooltip after second click. v-if works correct.
If you want to see tooltip after first click you must add Event Modifier .capture. Example: #click.capture="excludeCountry"
Docs,
Demo
I want to keep the value of a variable identical with the content of a textarea.
I don't want to use v-bind or v-model, because I have already bound the textarea with another value.
This is a notebook app, and the textarea is used to display the content of a note, so it has been bound using v-bind with a note object, like
<textarea cols="30" rows="3" v-bind:value="note"></textarea>
Now, I want to add the "edit note" functionality. So when the content of the textarea changes, I want to store its value into a variable, and when the "submit" button is clicked, I pass the value of the variable, which contains the new content of the note, to backend to update the note.
My question is, how to store the textarea's content into the variable after each time the content changes?
I think I cannot use v-model because this way the note will be changed right after the content of the textarea is modified (though not sent to backend), but this is not what I want. What I want is the note to be changed only after the "submit" button is clicked. Thus, I cannot use v-model
Should I use v-on:change? If so, how to get the content of the textarea?
Like,
<textarea v-on:change="updateTheVariable(I need to get the content of the textarea here)"> ... </textarea>
methods: {
updateTheVariable(content of the textarea) {
this.variable = content of the textarea
}
}
Thanks
I'm assuming this thing only shows up when you click some kind of edit button which is why you don't want to alter note so try something like this instead
<button type="button" v-if="!editMode" #click="editNote">Edit</button>
<form v-if="editMode" #submit="handleSubmit">
<fieldset :disabled="saving">
<textarea v-model="editingNote"></textarea>
<button type="submit">Edit</button>
</fieldset>
</form>
export default {
data: () => ({
note: 'whatever', // maybe it's a prop, maybe assigned later, doesn't matter
editMode: false,
editingNote: null, // this will be used to bind the edited value
saving: false
}),
methods: {
editNote () {
this.editingNote = this.note
this.editMode = true
this.saving = false
},
async handleSubmit () {
this.saving = true // disables form inputs and buttons
await axios.post('/notes/update', { note: this.editingNote}) // just an example
this.note = this.editingNote // or maybe use data from the response ¯\_(ツ)_/¯
// or if it's a prop, this.$emit('updated', this.editingNote)
this.editMode = false
}
}
}
As #Phil indicated in a deleted post, the right way to do it is
<textarea #input="updateTheVariable($event.target.value)"></textarea>
.
.
.
methods:{
updateTheVariable(value){
this.variable = value
}
}
I have an input which is bidden to property message. I have a set button , which I use for changing of input value programmatically. When the button is pressed, value of input is correctly changed to 'xxxx'. when I press clean button after that , the input is correctly cleaned but when I repeat pressing set and clean again the input does not get cleared anymore.
Working example is here:
https://codepen.io/dan-ouek/pen/rNBjxRO
<div class="container">
<div id='root' class="box">
<input ref="templateFilter" type='text' id='input' v-model='message'>
{{ message }}
<button #click="set">set</button>
<button #click="clean">clean</button>
</div>
</div>
new Vue({
el: '#root',
data: {
message: 'Hello Vue'
},
methods: {
set: function () {
let element = this.$refs.templateFilter
Vue.set(element, 'value', 'xxxx')
}, clean: function () {
this.message = ""
}
}})
Questions:
1) Is it possible to change input programmatically without working with bidden property value? Something like direct DOM manipulation:
let element = document.getElementsByClassName("templateFilter")[0]
element.value = 'xxxxx'
but with proper component refresh?
2) Why is the {{ message }} not refreshed after calling set method?
Why is the message not refreshed after calling set method?
When you type something on your input the message data gets updated via an event handler BUT when you set it programmatically the event handler is NOT triggered and that's why message was not getting updated / refreshed....
Solution :
a short solution to your issue would be just to mutate the message value this.message = "xxxx" but if you insist on making that programmatically you have to trigger the input event :
set: function() {
let element = this.$refs.templateFilter
Vue.set(element, 'value', 'xxxx')
element.dispatchEvent(new Event('input'))
}
Here is a Demo : codepen
I'm looking for the VueJS best practice for synchronizing between the input element and the switch element in the following piece of code:
<div class="filter panel">
<div class="field_title">Device</div>
<el-switch v-model="switches.device_switch" name="device"></el-switch>
<b-form-input v-model="device" placeholder="Device"></b-form-input>
</div>
If the input field contains any text I would like to set the v-model="switches.device_switch" to true.
How can I achieve this?
Set a watcher for the device property bound to the input. In the watcher, you can set the value of switches.device_switch based on the length of the device string:
watch: {
device: function(value) {
this.switches.device_switch = value.length !== 0;
}
}