How can I replace element in vue.js? - vue.js

Here's my code:
window.onload = (event) => {
new Vue({
el: "#test",
mounted: function() {
this.fetch();
setInterval(this.fetch, 60000);
},
data: function() {
return {
tracker: {
serverInfo: {
servername: ""
}
}
}
},
methods: {
fetch() {
fetch("https://pt.dogi.us/ParaTrackerDynamic.php?ip=pug.jactf.com&port=29071&skin=JSON")
.then(response => response.json())
.then(data => {this.tracker = data});
},
}
})
}
<script src="https://unpkg.com/vue#2.4.4/dist/vue.min.js"></script>
<div id="test">
<span style="font-weight:bold">SERVER NAME:</span> {{tracker.serverInfo.servername}}
Using vue.js how can I replace ^4Re^5fresh^11-PUG output element to
<span style="font-weight:bold">SERVER NAME:</span> <span style="color:blue">Re</span><span style="color:cyan">fresh</span><span style="color:red">1-PUG</span>
where ^4 stands for <span style="color:blue">
etc
Final result should looks like this: image

Use this regex to split the string: https://regex101.com/r/G2s23R/1
const regex = /(\^\d)([^\^]+)/gm;
// Alternative syntax using RegExp constructor
// const regex = new RegExp('(\\^\\d)([^\\^]+)', 'gm')
const str = `^4Re^5fresh^11-PUG`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
Then, I believe that you can process the remaining tasks.

Related

How to filter multiple JSON data using vuejs?

I would like to create a simple web apps that can display all json data
and user can filter it?
here it my code
I am using Vue 2
index.html
<div id="app">
<input type="input" id="txt-search" v-model="mySearch">
<select>
<option :value="post.id" v-for="post in searchBook"
>{{post.id}}</option>
</select>
</div>
script.js
var json_data = 'jsonfile.json'
var app = new Vue({
el: '#app',
data: {
posts: null,
mySearch:''
},
created: function () {
this.fetchData()
},
methods: {
fetchData: function () {
var xhr = new XMLHttpRequest()
var self = this
xhr.open('GET', json_data)
xhr.onload = function () {
self.posts = JSON.parse(xhr.responseText)
}
xhr.send()
}
},
computed: {
searchBook() {
return this.mySearch ? this.posts.filter(post => {
return post.title.includes(this.mySearch);
})
: this.posts;
}
}
})
It only filter title data
post.title.includes(this.mySearch)
Is it posible to filter all json data like
post.*.includes(this.mySearch)
function filterArray(arr, keyword) {
if (!keyword) return arr;
return arr.filter(obj =>
Object.values(obj)
.some(value => typeof value === 'string' && value.includes(keyword))
);
}
Usage:
computed: {
searchBook() {
return filterArray(this.posts, this.mySearch);
}
}
It is but is a little complicated. First, you must extract all the values from the object and filter every record to check if it contains the searched phrase.
Example:
const posts = [
{title: 'title1', author:'author1', comment: 'comment1'},
{title: 'foo', author:'author2', comment: 'comment2'},
{title: 'title3', author:'bar', comment: 'comment3'},
]
const serchedPhrase = 'author';
const filteredData = posts.filter((e) => {
const values = Object.keys(e).map(val => e[val]);
const filteredValues = values.filter((el) => el.includes(serchedPhrase));
return filteredValues.length > 0;
});
console.log(filteredData);

Vue.js : data is visible on console.log but not in DOM

I using google places-api to get a single or list of places. for each place in the list of places I would like to get an additional data (such as website) - this is done from another api (places details).
The problem is that I can see all the data in google console but not in the DOM - only the data from the the first API is visible ( {{item.website}} property is empty)
here is my code:
<input type="text" class="form-control" id="searchPlace" v-on:keyup.enter="getPlaces()" placeholder="Type a name, address etc..." v-model="placeToSearch">
<div v-for="(item, key) in objPlaces" :key="key">
{{ item.name }} | {{item.place_id}} | {{item.rating}} | {{item.website}}
</div>
<script>
var myObject = new Vue({
el: "#app",
data: {
placeToSearch: "",
objPlaces: null,
},
methods: {
getPlaces() {
let places = null;
axios
.get('#Url.Action("GetPlace")', { params: { name: this.placeToSearch }})
.then((res) => {
places = res.data.results;
})
.finally(() => {
// iterate each place to get its website
places.forEach(function (el) {
axios
.get('#Url.Action("GetPlaceDetails")',{params: { placeId: el.place_id }})
.then((res) => {
el["website"] = res.data.result.website;
});
this.objPlaces = places;
console.log(this.objPlaces); // all the data is displayed
});
});
},
},
please note I am using server side to get the details from google api
You may find it easier to use async/await rather than the callback functions.
const myObject = new Vue({
el: "#app",
data() {
return {
placeToSearch: "",
objPlaces: null,
}
},
methods: {
async getPlaces() {
const res = await axios.get('#Url.Action("GetPlace")', {
params: { name: this.placeToSearch },
});
const places = res.data.results;
this.objPlaces = places.map(async (el) => {
const res = await axios.get('#Url.Action("GetPlaceDetails")', {
params: { placeId: el.place_id },
});
el.website = res.data.results.website;
return el;
});
},
},
});
Note 1: I haven't tested this, but the general idea is there.
Note 2: Missing try/catch to handle errors from the API.
You're missing the return statement inside data function. The data option should always be a function in the context of components which returns a fresh object.
data(){
return {
placeToSearch: "",
objPlaces: null,
}
}
You can read more about it from the documentation: https://v2.vuejs.org/v2/guide/components.html#data-Must-Be-a-Function

Vue2 create component based on data

I want to create a component based on ajax api response or data which include:
template
data
methods - there may be several methods
Remark: response or data is dynamic and it is not saved in file.
I have tried to generate and return result like :
<script>
Vue.component('test-component14', {
template: '<div><input type="button" v-on:click="changeName" value="Click me 14" /><h1>{{msg}}</h1></div>',
data: function () {
return {
msg: "Test Componet 14 "
}
},
methods: {
changeName: function () {
this.msg = "mouse clicked 14";
},
}
});
</script>
and do compile above code :
axios.get("/api/GetResult")
.then(response => {
comp1 = response.data;
const compiled = Vue.compile(comp1);
Vue.component('result-component', compiled);
})
.catch(error => console.log(error))
I got error on Vue.compile(comp1) -
Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as
<script>, as they will not be parsed.
Thanks in advance
Your Api should return a JSON with every property required by a Vue component (name, data, template, methods), note that methods needs to be converted into an actual js function (check docs about that)
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
data() {
return {
apiComponent: { template: '<div>Loading!</div>' }
};
},
methods: {
loadApiComponent() {
setTimeout(() => {
this.buildApiComponent(JSON.parse('{"name":"test-component14","template":"<div><input type=\\\"button\\\" v-on:click=\\\"changeName\\\" value=\\\"Click me 14\\\" /><h1>{{msg}}</h1></div>","data":{"msg":"Test Componet 14 "},"methods":[{"name":"changeName","body":"{this.msg = \\\"mouse clicked 14\\\";}"}]}'));
}, 2000);
},
buildApiComponent(compObject) {
const {
name,
template,
data,
methods
} = compObject;
const compiledTemplate = Vue.compile(template);
this.apiComponent = {
...compiledTemplate,
name,
data() {
return { ...data
}
},
methods: methods.reduce((c, n) => {
c[n.name] = new Function(n.body);
return c;
}, {})
};
}
},
mounted() {
this.loadApiComponent();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<component :is="apiComponent" />
</div>

Function only gets called once in NuxtJs

I am using NuxtJs in my project, I a have list of checkboxes, on click of each checkbox I am sending an array of checkboxes to a my POST api which return data.
Here, when I check the first checkbox it returns the data. But when I check the second checkbox it does not does return the data.
I mean it only returns the data on single checkbox checked.
Its working with normal vuejs but not in nuxtjs
My Code:
<script>
import axios from "axios";
import uniq from "lodash/uniq";
export default {
async asyncData({ req, params }) {
let [storeInfo, feedsInfo] = await Promise.all([
axios.get(
process.env.apiURL +
"/stores/findOne?filter[where][store_name]" +
"=" +
params.id
),
axios.post(process.env.apiURL + "feeds/feedsByStores", {
stores: [params.id]
})
]);
return {
stores: storeInfo.data,
feeds: feedsInfo.data,
categories: uniq(feedsInfo.data.map(p => p.feed_category))
};
},
data() {
return {
checkedCategories: [],
checkedCategory: false,
selectedCategories: []
};
},
methods: {
feedsByCategories: function(categories) {
console.log(categories);
axios.post(process.env.apiURL + "feeds/feedsByCategories", {
categories: [categories]
}).then((res) => {
console.log(res);
})
},
categoryChecked: function(category, checked) {
this.display = "inline";
if (checked) {
this.selectedCategories.push(category);
console.log(this.selectedCategories);
this.feedsByCategories(this.selectedCategories);
} else if (!checked) {
const index = this.selectedCategories.indexOf(category);
this.selectedCategories.splice(index, 1);
this.feedsByCategories(this.selectedCategories);
if (this.selectedCategories == "") {
this.display = "none";
this.getFeeds();
}
}
if (!checked && this.selectedCategories.length === 0) {
this.getFeeds();
}
},
uncheckCategory: function(checkedCategory) {
this.checkedCategories = this.checkedCategories.filter(
name => name !== checkedCategory
);
const index = this.selectedCategories.indexOf(checkedCategory);
this.selectedCategories.splice(index, 1);
this.feedsByCategories(this.selectedCategories);
if (this.checkedCategories == "") {
this.display = "none";
this.getFeeds();
}
},
uncheckallCategories: function(event) {
this.checkedCategories = [];
this.display = "none";
this.search = "";
this.Search = "";
this.filteredCategories;
},
getFeeds() {
return this.feeds;
}
}
};
</script>
<template>
<v-layout>
<ul class="list-unstyled scrollbar">
<li v-for="(feedcategory, index) in categories" :key="feedcategory.id">
<input type="checkbox" name="category" #change="categoryChecked(feedcategory,$event.target.checked)"
:id="index + 1" :value="feedcategory" v-model="checkedCategories">
{{ feedcategory }}
</li>
</ul>
</v-layout>
</template>
My Typo,
I removed the brackets for my categories array and it worked:
feedsByCategories: function(categories) {
console.log(categories);
axios.post(process.env.apiURL + "feeds/feedsByCategories", {
categories: categories
}).then((res) => {
console.log(res);
})
}

VueJS: Setting data initially based on http response

So I have a template .vue file:
<template>
<div id="app">
<textarea v-model="input" :value="input" #input="update"></textarea>
<div v-html="compiledMarkdown"></div>
</div>
</template>
<script>
var markdown = require('markdown').markdown;
export default {
name: 'app',
data() {
return {
input: '# Some default data'
}
},
mounted: function () {
this.$nextTick(function () {
this.$http.get(window.location.pathname + '/data').then((response) => {
this.input = response.body.markdown;
}) })
},
computed: {
compiledMarkdown: function() {
this.$http.post(window.location.pathname, {
"html": markdown.toHTML(this.input)}).then(function() {
},function() {
});
return markdown.toHTML(this.input);
}
},
methods: {
update: function(e) {
this.input = e.target.value
}
}
}
</script>
In the mounted function I am trying to set input equal to the response of an HTTP request, but when you view this file this.input is still the same as it was initially declared. How can I change this.input inside the compiledMarkdown function to be this.input in the mounted function. What other approaches might I take?
You can not call a async method from a computed property, you can use method or watcher to run asynchronous code, from docs
This is most useful when you want to perform asynchronous or expensive operations in response to changing data.
You have to ran that relevant code when input changes, like following:
var app = new Vue({
el: '#app',
data: {
input: '# Some default data',
markdown : ''
},
methods: {
fetchSchoolData: function (schoolId) {
var url = this.buildApiUrl('/api/school-detail?schoolId=' + schoolId);
this.$http.get(url).then(response => {
this.schoolsListData = response.data;
}).catch(function (error) {
console.log(error);
});
},
},
mounted: function () {
this.$nextTick(function () {
this.$http.get(window.location.pathname + '/data').then((response) => {
this.input = response.body.markdown;
})
})
},
watch: {
// whenever input changes, this function will run
input: function (newInput) {
this.$http.post(window.location.pathname, {
"html": markdown.toHTML(this.input)}).then(function() {
},function() {
this.markdown = markdown.toHTML(this.input);
});
}
},
Have a look at my similar answer here.