vuejs textarea 1 value per row - javascript

I have a problem
I want to get a value for each row value of posts in textarea
i am giving an example
as in this image
I want to have a value for each line written
When I press the enter key and go to the bottom line and write there, I want to get the text written on that second line as a second value.
my goal is to be able to draw for each column
vuejs compisitions api or option api

Try this.
<script>
import { ref, computed } from 'vue'
export default {
setup() {
const textAreaText = ref('')
const values = computed(() => textAreaText.value.split('\n'))
return { textAreaText, values }
}
}
</script>
<template>
<textarea v-model="textAreaText"></textarea>
<p>
{{ values }}
</p>
</template>

<template>
<div>
<textarea v-model="values"></textarea>
</div>
</template>
<script>
export default {
data() {
return {
values: ''
}
},
computed: {
valuesArray() {
return this.values.split('\n')
}
},
watch: {
valuesArray(newVal) {
this.values = newVal.join('\n')
}
}
}
</script>

Related

How to use plain javascript variables in vue 3 component?

I have a javascript file with some variables and I want to use them in a vue component like this:
<template>
<div> Hello {{ personData.name }} {{ personData.last }} </div>
<button #click="signOut"> Sign Out </button>
</template>
<script>
import { personData } from '<path>'
export default {
...
methods: {
signOut() {
personData.signed_in = false;
}
}
}
</script>
JS file:
export var personData = {
name: '<name>',
last: '<last>',
signed_in: true,
}
It says personData is undefined but obviously it isn't, and also that it was accessed but not defined on instance. I'm new to Vue so I have no idea what I'm doing wrong. Also its important that they are global and not part of the component
Made nothing appear on the page at all
The problem is, you are importing a variable and just using it inside a Vue instance.
VueJS has to know which are reactive data so that it can update the DOM based on its value.
So, you make the following changes to make it work:
<template>
<div> Hello {{ personData.name }} {{ personData.last }} </div>
<button #click="signOut"> Sign Out </button>
</template>
<script>
import { personData } from './presonalData.js'
export default {
data () {
return {
personData //register as reactive data
}
},
methods: {
signOut() {
personData.signed_in = false;
}
}
}
</script>

this.$emit() is not a function while trying to change state in parent component from child in composition API in vue 3

//Parent component
<template>
<childComp #onchangeData='changeData' />
</template>
<script>
setup() {
const state = reactive({
data: 'anything
});
function changeData(v){
state.data = v
}
return { changeData}
},
</script>
//Child
<template>
<button #click='change('hello')' />
</template>
<script>
setup() {
function change(v){
this.$emit('onchangeData', v)
}
return{change}
},
</script>
I am struggling to change the parents' reactive state from the child's button click. It's saying this.$emit is not a function. I tried many ways like using #onchangeData='changeData()' instead of #onchangeData='changeData', using arrow functions etc. But nothing works. Here, I wrote an example and minimal code to keep it simple. But I hope my problem is clear.
Look at following snippet, this is not the same in composition as in options API, so you need to use emit passed to setup function:
const { reactive } = Vue
const app = Vue.createApp({
setup() {
const state = reactive({
data: 'anything'
});
function changeData(v){
state.data = v
}
return { changeData, state }
},
})
app.component("ChildComp", {
template: `
<div>
<button #click="change('hello')">click</button>
</div>
`,
setup(props, {emit}) {
function change(v){
emit('onchangeData', v)
}
return { change }
},
})
app.mount('#demo')
<script src="https://unpkg.com/vue#3/dist/vue.global.prod.js"></script>
<div id="demo">
<child-comp #onchange-data='changeData'></child-comp>
<p>{{ state.data }}</p>
</div>

Using external callback function data inside vuejs component

Hello and Happy holidays !!
I need advice on how I could get data from an external function that generate a zipfile into my vuejs component, to create a progress bar for JSZip plugin: https://stuk.github.io/jszip/documentation/api_jszip/generate_async.html
I import my file :
import { generateZIP } from "#/utils/downloader.js";
and call it inside vuejs from a method trigger by a button:
<template>
...
<div v-for="result of results" :key="result.item.refID">
<section class="row" #click="selectByRow(result.item)">
<input
type="checkbox"
:id="result.item.refID"
:value="result.item.refID"
v-model="checkedItems"
class="checkbox"
/>
</div>
<!-- FOUND RESULTS -->
<div class="name">{{ result.item.marketingName }}</div>
</section>
</div>
<!-- Download all checked items -->
<div>
<button
v-if="checkedItems.length > 1"
#click="downloadAll(checkedItems)"
class="button"
>
Download Selection
</button>
</template>
...
<script>
import { mapState, mapActions, mapMutations, mapGetters } from "vuex";
import { generateZIP } from "#/utils/downloader.js";
...
export default {
data() {
return {
// Path to point to pictures storage
domainName: this.$domainName,
// Array to gather search results
searchArray: [],
checkedItems: [],
// make a special array for row selection
checkedRow: []
};
},
methods:
downloadAll(files) {
// Prepare path
const fullPath = `${this.domainName}/files/${this.reqPath}/`;
const filesArray = [];
files.forEach(fileID => {
let obj = this.results.find(value => value.item.refID == fileID);
if (obj.item.images !== undefined) {
filesArray.push(obj.item.images);
}
});
generateZIP(filesArray.flat(), fullPath);
},
selectByRow(resultID) {
// Check if select resultID.refID is already in checkedItems and store it in variable if its present.
const isInArray = this.checkedItems.find(name => name === resultID.refID);
// if the ref not in array, add it
if (!isInArray) {
this.checkedItems.push(resultID.refID);
// Add checkedRow full information object
this.checkedRow.push(resultID);
} else {
// if already in array, remove it
this.checkedItems = this.checkedItems.filter(
name => name !== resultID.refID
);
this.checkedRow = this.checkedRow.filter(
name => name.refID !== resultID.refID
);
}
...
Everything working, now I add some feedback showing the zip progress. There is an available callback function "updateCallback" that I'll call in my downloader.js
zip.generateAsync({type:"blob"}, function updateCallback(metadata) {
console.log("progression: " + metadata.percent.toFixed(2) + " %");
if(metadata.currentFile) {
console.log("current file = " + metadata.currentFile);
}
})
...
export {
generateZIP
}
Cool it displays progression in my console log.
But HOW could I import this metadata object into vue to display it in my app ?
Thanks a lot !
Use data properties in your vue component.
Inside the callback, link your instance (this) to local var, to pass value between callback data and reactive property. For example: let var=this

How to change VueJS's <slot> content before component creation

I have a VueJS component,
comp.vue:
<template>
<div>
<slot></slot>
</div>
</template>
<script>
export default {
data () {
return {
}
},
}
</script>
And I call this Vue component just like any other component:
...
<comp>as a title</comp>
<comp>as a paragraph</comp>
...
I would like to change comp.vue's slot before it is rendered so that if the slot contains the word "title" then the slot will be enclosed into an <h1>, resulting in
<h1>as a title</h1>
And if the slot contains "paragraph" then the slot will be enclosed in <p>, resulting in
<p>as a paragraph</p>
How do I change the component slot content before it is rendered?
This is easier to achieve if you use a string prop instead of a slot, but then using the component in a template can become messy if the content is long.
If you write the render function by hand then you have more control over how the component should be rendered:
export default {
render(h) {
const slot = this.$slots.default[0]
return /title/i.test(slot.text)
? h('h1', [slot])
: /paragraph/i.test(slot.text)
? h('p', [slot])
: slot
}
}
The above render function only works provided that the default slot has only one text child (I don't know what your requirements are outside of what was presented in the question).
You can use $slots(https://v2.vuejs.org/v2/api/#vm-slots):
export default {
methods: {
changeSlotStructure() {
let slot = this.$slots.default;
slot.map((x, i) => {
if(x.text.includes('title')) {
this.$slots.default[i].tag = "h1"
} else if(x.text.includes('paragraph')) {
this.$slots.default[i].tag = "p"
}
})
}
},
created() {
this.changeSlotStructure()
}
}

VueJS method not returning response from Axios

Trying to figure this out for awhile now and I know it is something simple but can not seem to figure out the issue. My output is {} when I am trying to return a Axios response. When I do not return the entire axios.post my output is nothing. But when I console.log the data it shows up fine in the console. So I know I am getting the data correctly. Below is my test code. Not sure what I am doing wrong, if anyone has a idea it would be greatly appreciated.
<template>
<div>
{{ fetch_name('my_name') }}
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
}
},
methods: {
fetch_name(name) {
return axios.post('example.com/api/names', {custom: 'SELECT name FROM `names` WHERE name = "'+name+'"'}).then(response => {
console.log(response.data[0].name)
return response.data[0].name
})
}
}
}
</script>
Solution for your case:
<template>
<div>
{{ fetch_name('my_name') && result }}
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
result: 'Loading...',
}
},
methods: {
fetch_name(name) {
return axios.post('example.com/api/names', {custom: 'SELECT name FROM `names` WHERE name = "'+name+'"'}).then(response => {
console.log(response.data[0].name)
this.result = response.data[0].name;
return response.data[0].name
})
}
}
}
</script>
But I think better modify logic something like this:
Solution for with control name in UI:
<template>
<div>
<input v-model="name">
{{ result }}
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
name: null,
result: 'Wait for typing',
}
},
watch: {
name(name) {
this.result = 'Loading...';
axios.post('example.com/api/names', {custom: 'SELECT name FROM `names` WHERE name = "'+name+'"'})
.then(response => {
this.result = response.data[0].name;
return response.data[0].name
})
}
},
}
</script>
return response.data[0].name
isn't returning from fetch_name fetch name returns as soon as it does the post....
what you need to do is put the response into your data, then bind to your data, not the method. When the response to post comes in, it will then trigger the UI update.
Also, sending SQL from the client side seems super dangerous.

Categories