So I'm going to be explaining this in the best way possible as I don't understand what might be causing this issue on my end as I feel like I've followed all of the directions and keep hitting a brick wall.
Here is my vue.js app:
new Vue({
name: 'o365-edit-modal-wrapper',
el: '#o365-modal-edit-wrapper',
data: function() {
const default_apps = [
{
'post_title': 'Excel',
}, {
'post_title': 'Word',
}, {
'post_title': 'SharePoint',
}];
console.log(default_apps);
const default_apps1 = this.get_array_of_post_objects('application_launcher');
console.log(default_apps1);
return {
available_list: [],
selected_list: default_apps.map(function(name, index) {
return {
name: name.post_title,
order: index + 1,
fixed: false
};
}),
}
},
methods: {
get_array_of_post_objects(slug) {
let items = [];
wp.api.loadPromise.done(function () {
const Posts = wp.api.models.Post.extend({
url: wpApiSettings.root + 'menus/v1/locations/' + slug,
});
const all_posts = new Posts();
all_posts.fetch().then((posts) => {
items.push(...posts.items);
});
});
return items;
},
},
computed: {
dragOptions() {
// Pass in additional <draggable> options inside the return for both lists.
return {
tag: 'div',
group: 'o365apps',
disabled: !this.editable,
ghostClass: "ghost",
};
},
},
});
Inside my methods, I have a method called get_array_of_post_objects which returns an array of objects that I'm pulling through.
So inside data, I'm console logging my manual default_apps and my default_apps1 which is the method. Both of the arrays of objects have post_title: "something" inside.
Here is the return that I'm getting:
Inside my mapping, when I define default_apps, my IDE returns some result for name but when I switch it over to default_apps1, it's not finding any results as shown below:
I don't know what else to look at - All help would be appreciated!
Here is the HTML code if that is needed:
<div class="column is-half-desktop is-full-mobile buttons">
<nav class="level is-mobile mb-0">
<div class="level-left">
<div class="level-item is-size-5 has-text-left">Selected</div>
</div>
<div class="level-right">
<div class="level-item" #click="orderList()"><i class="fas fa-sort-alpha-up is-clickable"></i></div>
</div>
</nav>
<hr class="mt-1 mb-3">
<!-- Decorator: # also known as v-on: -->
<!-- Bind: : also known as v-bind: -->
<draggable class="list-group"
v-model="selected_list"
v-bind="dragOptions"
:move="onMove"
#add="onAdd"
#remove="onRemove"
#start="isDragging=true"
#end="isDragging=false">
<button class="button is-fullwidth is-flex list-group-item o365_app_handle level is-mobile" v-for="(app, index) in selected_list" :key="app.order">
<div class="level-left">
<span class="icon" aria-hidden="true">
<img :src="`<?= Path::o365('${app.name}' . '.svg'); ?>'`" />
</span>
<span>{{app.name}}</span>
</div>
<div class="level-right is-hidden-desktop">
<span class="icon has-text-danger is-clickable" #click="remove(index)">
<i class="fas fa-times"></i>
</span>
</div>
</button>
</draggable>
</div>
I'm not 100% sure what your app is supposed to do, so modify it for your needs.
Here the selected_list will be empty first.
Then we call your method, which is asynchronous, and once it's done selected_list gets populated.
new Vue({
name: 'o365-edit-modal-wrapper',
el: '#o365-modal-edit-wrapper',
data: function() {
return {
available_list: [],
selected_list: [],
}
},
created() {
this.get_array_of_post_objects("add-your-slug")
},
methods: {
get_array_of_post_objects(slug) {
wp.api.loadPromise.done(function() {
const Posts = wp.api.models.Post.extend({
url: wpApiSettings.root + 'menus/v1/locations/' + slug,
});
const all_posts = new Posts();
all_posts.fetch().then((posts) => {
// You might want to modify posts for your needs
this.selectedList = posts
});
});
},
},
});
Related
<template>
<div id="profile" class="collection with-header">
<div class="profview">
</div>
<div class="search blue">
<div class="input-field">
<div class="input-field">
<i class="material-icons prefix"></i>
<input type="text" id="usernames" v-model="usernames" />
<label class="white-text" for="email">Enter username</label>
</div>
<button
v-on:click="followlist"
class="btn btn-large btn-extended grey lighten-4 black-text"
>
Search
</button>
</div>
</div>
<div class="list right red">
{{ word }}
<li v-for="user in users" v-bind:key="user.id" class="collection-item">
<button v-on:click="followlist">{{user.name}}</button>
<!--<button v-on:click="seeoptions = !seeoptions">{{user.name}}</button>-->
<div id="options" v-if="seeoptions">
<li><button>Follow</button></li>
<li><button>Block</button></li>
<li><button>View Profile</button></li>
</div>
</li>
</div>
</div>
</template>
<style>
template{
background-color: blueviolet
}
</style>
<script>
//lets see if we can implement the search function using login as
// a template, change data to match with what u need
import db from './firebaseInit'
import firebase from "firebase";
var auth = firebase.auth();
var exists = false;
export default {
name: "followlist",
data: function () {
return {
users: [],
loading: true,
usernames: "",
word: 'This is a friends list',
content: 'Info of User',
content2: 'A search bar',
//seeoptions1: false,
// seeoptions2: false,
//seeoptions3: false
}
},
methods:{
followlist: function(e) {
db.collection('users').get().then((querySnapshot) =>{
this.loading = false
//console.log("succes");
//let inputtedname = document.getElementById("username").value;
//let stringName = inputtedname.toString()
querySnapshot.forEach((doc) => {
// console.log("succes");
// console.log(stringName);
var tempname = this.usernames;
var temp = doc.data().username;
// console.log(this.username);
// console.log(temp);
var curruser = this.username;
if(tempname == temp){
console.log(doc.data().username)
}
else
console.log("dont know")
})
// console.log(stringName)
})
},
},
created () {
// Boolean userExists = false;
db.collection('users').orderBy('dept').get().then((querySnapshot) => {
this.loading = false
querySnapshot.forEach((doc) => {
const data = {
'id': doc.id,
'name': doc.data().name,
'dept': doc.data().dept,
//'position': doc.data().position
}
this.users.push(data)
})
})
}
}
</script>
ignore all the commented out console logs, anyways, i tried setting both to a variable, i tried doing it by straight comparing this.username to the one in database. its getting the username from the database correctly, ive console logged it and it worked fine, outputted all the usernames from database. however at the if statement, it will not compare them correctly if they are matches. also ignore the bottom created () section, its nnot doing anything currently. just was used to test
Its probably due to a space in one of the string.
if(tempname.trim() == temp.trim()) {
console.log(doc.data().username)
}
I want to sort my JSON by date, and if there are multiple entries for a specific date, group all of them into the specific date.
This is my JSON:
[
{
"id":"3",
"time":"20:00",
"hometeam":"AC Milan",
"awayteam":"Juventus",
"prediction":"Under 2.5",
"odds":"1.75",
"competition":"Serie A",
"status":"lost",
"date":"01-11-2019"
},
{
"id":"4",
"time":"21:00",
"hometeam":"FCSB",
"awayteam":"Dinamo",
"prediction":"Draw",
"odds":"1.12",
"competition":"Liga 1",
"status":"",
"date":"01-11-2019"
},
{
"id":"1",
"time":"16:00",
"hometeam":"Chelsea",
"awayteam":"Arsenal",
"prediction":"Over 2.5",
"odds":"1.32",
"competition":"Premier League",
"status":"won",
"date":"31-10-2019"
},
{
"id":"2",
"time":"18:00",
"hometeam":"Manchester United",
"awayteam":"Liverpool",
"prediction":"1x2",
"odds":"1.45",
"competition":"Premier League",
"status":"won",
"date":"31-10-2019"
}
]
I want to order my JSON by date, and then have every match grouped by specific date and display them in HTML. So far, I'm displaying these 4 games, but I'm adding the date to every game; I would like to have the date, then the 2 games from 01-11-2019, again the date, 31-10-2019, then the rest of the 2 matches.
Here's the AJAX and HTML:
function updateList() {
jQuery.ajax({
type: "GET",
url: url
dataType: 'json',
timeout: 5000,
crossDomain: true,
cache: false,
success: function(data) {
console.log(JSON.stringify(data));
var groupedData = _.groupBy(data, function(d){return d.date});
//console.log(groupedData);
var htmlText = data.map(function(o){
return `
<div class="norm"><i class="icon-hourglass-time"></i>${o.date}</div>
<ul class="stage clearfix">
<li class="scene">
<!-- <div class="trigger"></div> -->
<div class="face" ontouchend="return true">
<a class="calendar-hour poster tasklist-gray">
<div class="max-constrain">
<div class="first-20">
<div class="cal-from"><strong>${o.time} <small>GMT</small></strong>
</div>
</div>
<div class="second-45">
<div class="teams">${o.hometeam}
<br><small>vs</small>
<br>${o.awayteam}</div><em><i class="fa fa-map-marker"></i>${o.competition}</em>
</div>
<div class="third-35 last-column">
<div class="over-under">
<div class="over-under-icon">
<div class="over-under-text-over uppercase">
<div class="over-under-number">${o.prediction}</div>
<div class="odd-number">
${o.odds}
</div>
</div>
<div class="touch-section uppercase"><span class="statusValue">${o.status}</span></div>
</div>
</div>
</div>
</div>
</a>
<div class="info">
<div class="result-top-unch uppercase"><i class="fa fa-pause"></i>…</div>
</div>
</div>
</li>
</ul>
`;
});
jQuery('.container-fullscreen').append(htmlText);
},
error: function(data) {
console.log(JSON.stringify(data));
}
});
}
Thanks for the help!
Actually what you want to do has to be done in two steps.
First, group your objects by date, you can do this with lodash, since it's already in your code.
With an ES6 approach, you could do this by defining the following function:
function groupBy(list, keyGetter) {
const map = new Map();
list.forEach((item) => {
const key = keyGetter(item);
const collection = map.get(key);
if (!collection) {
map.set(key, [item]);
} else {
collection.push(item);
}
});
return map;
}
It takes two arguments: your array and the function that'll be used to verify on which property it should group your data.
matchMap = groupBy(foo, match => match.date)
You have plenty example avalaible on SO, i checked this post
Then you just have to sort the array by dates:
let matchArray = Array.from(matchMap )
const sortedArray = matchArray.sort( (a, b) => {
const dateArrayA = a[1][0].date.split('-');
const dateArrayB = b[1][0].date.split('-');
return new Date(dateArrayA[2], dateArrayA[1]-1, dateArrayA[0]) > new Date(dateArrayB[2], dateArrayB[1]-1, dateArrayB[0])
})
since the date property is not a valid date but a string, you have to reconstruct it when comparing the different entries.
Then the result will be a dictionary with the date as key and ordered by it.
EDIT
Fetching data:
for(i=0;i<matchArray.length;i++)
{
for(j=0;j<matchArray[i][1].length;j++){
const currentMatch = matchArray[i][1][j];
//Your display logic
}
}
Hope it helps !
I am creating a simple SPA using vue.js and axioz as a scripts (not cli, etc)
So far I am able to pull data from a json then render and paginate the list,and when an item is clicked I am able to console log the data for the specific entry.
HTML
<!--app-->
<div id="app">
<!--articles-->
<div class="row" style="background: #111; padding: 8em 0; width: 50%;">
<div class="ctr">
<div class="row articles page_content" style="padding: 0;">
<ul>
<li v-for="(post) in displayedPosts" #click="getSingle(post.id)">
<router-link :to="{ path: '/post/'+ post.id}" class="flex" >
<div class="row article_thumb">
<img :src="post.url" :alt="post.title"/>
</div>
<div class="row article_excerpt">
<h3 class="title">{{post.title }}</h3>
</div>
</router-link>
</li>
</ul>
</div>
<div class="row pagination">
<button type="button" v-if="page != 1" #click="page--"> << </button>
<button type="button" v-for="pageNumber in pages.slice(page-1, page+5)" #click="page = pageNumber"> {{pageNumber}} </button>
<button type="button" #click="page++" v-if="page < pages.length"> >> </button>
</div>
</div>
</div>
<!--articles-->
<div class="row" style="background: #000; padding: 8em 0; width: 50%;">
<div class="flex router">
<router-view></router-view>
</div>
</div>
</div>
<!--app-->
VUE.JS
const Home = {
template: "<div><h1>Click an article to update this view</h1></div>"
};
//post
var Post = {
template:
'<div class="row"><h1>Display data for Post ID # {{$route.params.id}} here</h1><p style="color: red;">This is where I am stuck, cant display the post data, see example below.</p><p>{{title}}</p></div>',
//post methods
methods: {
//get single post
getSingle: function(id) {
var self = this;
this.id = this.$route.params.id;
this.title = this.title;
axios
.get(this.baseUrl, {
params: {
id: this.id,
}
})
.then(response => {
this.post = response.data;
this.title = response.data.title;
console.log(this.title);
console.log(this.post);
console.log("You clicked post ID #" + this.id);
})
.catch(response => {
console.log(error);
});
}
},
//post methods
//post data
data() {
return {
baseUrl: "https://jsonplaceholder.typicode.com/photos",
posts: [],
title: this.title
};
},
//post created
created() {
this.getSingle(this.$route.params.id);
},
watch: {
"$route.params": {
handler(newValue) {
const { id } = newValue;
this.getSingle(id);
},
immediate: true
}
}
};
//post
//router
const router = new VueRouter({
routes: [
{ path: "/", component: Home },
{ path: "/post/:id", component: Post }
]
});
//initial state
var paginationApp = new Vue({
el: "#app",
router: router,
data: {
posts: [],
baseUrl: "https://jsonplaceholder.typicode.com/photos",
page: 1,
perPage: 2,
pages: []
},
//initial state methods
methods: {
//get single
getSingle() {},
//get posts
getPosts() {
axios
.get(this.baseUrl)
.then(response => {
this.posts = response.data;
})
.catch(response => {
console.log(response);
});
},
//set pages
setPages() {
let numberOfPages = Math.ceil(this.posts.length / this.perPage);
for (let index = 1; index <= numberOfPages; index++) {
this.pages.push(index);
}
},
//paginate
paginate(posts) {
let page = this.page;
let perPage = this.perPage;
let from = page * perPage - perPage;
let to = page * perPage;
return posts.slice(from, to);
}
},
//created
created() {
this.getPosts();
},
//watch
watch: {
posts() {
this.setPages();
}
},
//computed
computed: {
displayedPosts() {
return this.paginate(this.posts);
}
}
});
//initial state
Or see this codepen for full example https://codepen.io/flashvenom/pen/YozyMx and be sure to checkout the console log.
My problem is i cannot console log the title or any internal fields of the data object, as I want to be able to add the title etc into the view area.
Any help or pointers would be much appreciated.
The response is in array form and you cannot access array object element without looping array.
If you wish to get title of first post, then you can do as shown below,
this.title = response.data[0].title
To access all posts title, you can use v-for loop in you vue template. Here is little example on how you can accomplish that,
<div v-for="post in posts">
<span>{{ post.title }}</span>
</div>
I want to display multiples html tables of tools (1 table = 1 tool's categorie / 1 tr = 1 tool).
data() {
return {
cats: '',
tools: [],
};
},
methods: {
getToolCats() {
var rez = getToolCats();
rez.then(data => this.receiveCats(data) )
},
receiveCats(_cats){
this.cats = _cats;
_cats.forEach(cat => {
getToolsByCat(cat.href).then(data => this.tools[cat.href] = data);
});
console.log(this.tools);
},
},
mounted() {
this.getToolCats();
},
cats (ie categories) is an array populated with an API call. Then for each cat, an API Call give me a tool list of that cat, that I place into the tools array (this.tools[cat.href] = data).
Here is the display code :
<div v-for="cat in cats" :key="cat.href" class="tbox col-xs-12 col-sm-6">
....
<table class="table table-hover">
<tr v-for="tool in tools[cat.href]" :key="tool.href">
<td>...</td>
</tr>
</table>
....
</div>
If i'm using a single var to store lthe tool list, all is OK. But while I don't know how many cats I'm going to have, I can't create a car for each category.
I think the problem could be there :
Using an array in v-for with a key not defined at mounted state :
v-for="tool in tools[cat.href]
I'll appreciate any help !
Vue can't detect dynamic property addition in this.tools[cat.href] = data, but it would detect the change with this.$set or Vue.set in this.$set(this.tools, cat.href, data):
new Vue({
el: '#app',
data() {
return {
cats: [],
tools: {}, // <-- make this an object (not an array)
};
},
mounted() {
this.getToolCats();
},
methods: {
getToolCats() {
// setTimeout to simulate delayed API calls...
setTimeout(() => {
this.cats = [
{ href: 'https://google.com' },
{ href: 'https://microsoft.com' },
{ href: 'https://apple.com' },
{ href: 'https://amazon.com' },
];
this.cats.forEach((cat, i) => {
setTimeout(() => {
const data = { href: cat.href };
this.$set(this.tools, cat.href, data); // <-- use this.$set for dynamic property addition
}, i * 1000);
})
}, 1000);
}
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<div v-if="!cats || cats.length == 0">Loading...</div>
<div v-for="cat in cats" :key="cat.href" v-else>
<table>
<tr v-for="tool in tools[cat.href]" :key="tool.href">
<td>cat.href: {{cat.href}}</td>
</tr>
</table>
</div>
<pre>tools: {{tools}}</pre>
</div>
Currently i am implementing a like system into my laravel project with Vue js. The scenario is after users liked the post. It will showing the total like of the post beside the like button. If using controller and passing data into view is easy to be done. But when change to Vue js i have no idea how to do it. This is my Like.vue file.
<template>
<button class="btn btn-primary" v-if="!auth_user_likes_post" #click="like()">
Support
</button>
<button class="btn btn-primary" v-else #click="unlike()">
Unsupport
</button>
export default {
mounted(){
},
props: ['id'],
computed: {
likers() {
var likers = []
this.post.likes.forEach( (like) => {
likers.push(like.user.id)
})
return likers
},
auth_user_likes_post() {
var check_index = this.likers.indexOf(
this.$store.state.auth_user.id
)
if (check_index === -1)
return false
else
return true
},
post() {
return this.$store.state.posts.find( (post) => {
return post.id === this.id
})
}
},
methods: {
like() {
this.$http.get('/like/' + this.id)
.then( (resp) => {
this.$store.commit('update_post_likes', {
id: this.id,
like: resp.body
})
})
},
unlike() {
this.$http.get('/unlike/' + this.id)
.then( (response) => {
this.$store.commit('unlike_post', {
post_id: this.id,
like_id: response.body
})
})
}
}
}
The like and unlike functions has been done and working perfectly. Now i just need to show the total number.
This is Feed.vue file. The like was adding to this page.
<div class="post-description">
<p>{{ post.content }}</p>
<div class="stats">
<like :id="post.id"></like>
<a href="#" class="stat-item">
<i class="fa fa-retweet icon"></i>12
</a>
<a href="#" class="stat-item">
<i class="fa fa-comments-o icon"></i>3
</a>
</div>
</div>
If my function cannot be achieved the expected scenario then can you recommend other ways which can do that?
I have the returned array with likers. But at beginning i never though using this could be achieved my goal. So this {{ likers.length }} actually can show the total number.