I am creating a time application using the Openweather API. I try to show the meteorological icon corresponding to the selected city and the meteorological state.
My code is as follows:
HTML:
<div class="column">
<div class="media-content">
<div class="content">
<p>
<strong>
<h1 class="has-text-inf o"> {{ ciutatActual.weather[0].icon }} </h1>
</strong>
</p>
</div>
</div>
</div>
javascript:
var vm = new Vue({
el: '#eltemps',
data: {
selectedCity: "",
ciutatActual: null,
ciutats: [
"Barcelona",
"Lleida",
"Zaragoza",
"Sevilla",
"Madrid",
"Paris",
"Melbourne",
"Moscow",
"Pekin",
"Marrakech"]
},
created: function () {
this.selectedCity = this.ciutats[0]
},
watch: {
selectedCity: function (){
this.getWeather(this.selectedCity)
}
},
methods: {
getWeather(city) {
const url = 'https://api.openweathermap.org/data/2.5/weather?q=' + city + '&units=metric&lang=ca&appid=8660dddfbe5f16ee37dbd6883d8f07d5';
fetch(url)
.then(function (response) {
return response.json()
})
.then(function (item) {
vm.ciutatActual = item;
})
.catch(function(error) {
console.log(error);
})
},
itemClicked: function(item) {
this.getWeather();
this.onClick(item);
}
}
})
The ruling comes from here: {{ciutatactual.weather [0] .icon}}
that instead of showing the icon it shows me just one code
Related
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
});
});
},
},
});
I'm starting with vue.js and firebase and I have a chat system using firebase. I get all the users’ id that have sent messages to me. So in my database I get their data and list with a v-for.
After listing them I get their messages from FB to list in a message box below each user.
Everything is working fine but I cannot get sent messages instantly after sending them.
I made a workaround with push() to append each sent message to data property but I'd like to know if there is a better way to do that with vue.js.
I've tested with plain javascript (separately with one message box) and the chat is updated on every sent message.
Is there a way to make this work without replacing all data object or calling all the listing process again? I tried with Vue's Reactivity but I could not make it work as expected.
<div v-if="isLoading == true" id="loading"><img class="loading" src="../assets/img/loading.gif" /></div>
<div v-if="isLoading == false" class="row messages-row" v-for="(item, index) in memberData" :key="index">
<div class="col-md-4 col-12">
<div class="messages-profile-infos">
<div class="messages-profile-infos-img img-fluid" v-bind:style="{'background-image': 'url(http://localhost/backend/imgs/'+item.memberProfileImg + ')' }"></div>
<div class="messages-profile-infos-text">
<p>{{ item.memberName }} {{ item.memberLastname }}</p>
<p>{{ item.memberCity }} - {{ item.memberState }}</p>
</div>
</div>
</div>
<div class="col-md-2 col-12">
<div class="messages-btns">
<button class="btn trade-btn" #click="showConversation(item.memberID)">Messages</button>
</div>
</div>
<div class="col-md-6 col-12">
<div class="messages-status">
<a class="btn border btn-circle text-uppercase confirm-service-btn" href="javascript:void(0);">
Confirm
</a>
<a class="btn border btn-circle text-uppercase cancel-service-btn" href="javascript:void(0);">Cancel</a>
</div>
</div>
<!-- conversation box -->
<div v-if="memberBox == item.memberID" class="conversation-container" :id="item.memberID">
<div v-for="(tour, index) in item.tours" :key="index" id="tourOnConversation" class="tourOnConversation">
<span>Tour:</span>
<span><strong>{{ tour.title }}</strong></span>
</div>
<div id="messages-container" class="messages-container" :key="item.memberID">
<div v-for="message in item.messages" class="d-flex" :class="[message.uid != myID ?'justify-content-start':'justify-content-end']">
<span class="badge badge-pill" :class="[message.uid != myID ?'badge-primary':'badge-secondary']">{{ message.message }}</span>
</div>
</div>
<div class="message-typing-container">
<form id="messages_form" action="" method="POST">
<div class="typing-container">
<input id="message" v-model="messages" type="text" class="message-typing" autocomplete="off" />
<input class="send-message" type="submit" value="Send" #click="sendMessage(item.memberID, item.tour)" />
</div>
</form>
</div>
</div>
<hr />
</div>
var firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxxxxxxxxxxxxxx",
databaseURL: "xxxxxxxxxxxxxxxxxxxxx",
projectId: "xxxxxxxxxxxxx",
storageBucket: "xxxxxxxxxxxxxxxxxxx",
messagingSenderId: "xxxxxxxxxxxxx",
appId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
};
firebase.initializeApp(firebaseConfig);
let app = new Vue({
el: "#app",
data() {
return {
memberData: {},
myMessages: [],
memberMessages: [],
myID: userID,
messages: "",
messageBox: 0,
conversation: {},
isLoading: true,
memberBox: 0,
};
},
created: function () {
this.getAllMessages();
},
methods: {
scrollBox: function () {
let messagebox = document.querySelector("#messages-container");
messagebox.scrollTop = messagebox.scrollHeight;
},
getAllMessages: function () {
let distinct = "";
firebase
.firestore()
.collection("messages")
.where("memberID", "==", `${this.myID}`)
.orderBy("date")
.onSnapshot((res) => {
let members = [];
res.forEach((doc) => {
members.push(doc.data().uid);
});
distinct = Array.from(new Set(members));
this.getUserToTalk(distinct);
});
},
getMyMessages: function (memberID) {
let myMessages = [];
firebase
.firestore()
.collection("messages")
.where("uid", "==", `${this.myID}`)
.where("memberID", "==", `${memberID}`)
.orderBy("date")
.onSnapshot((res) => {
res.forEach((doc) => {
myMessages.push(doc.data());
});
});
return myMessages;
},
getMessages: function (memberID) {
let messages = [];
firebase
.firestore()
.collection("messages")
.where("uid", "==", `${memberID}`)
.where("memberID", "==", `${this.myID}`)
.orderBy("date")
.onSnapshot((res) => {
res.forEach((doc) => {
messages.push(doc.data());
});
});
return messages;
},
getUserToTalk: function (memberID) {
axios
.post("http://localhost/backend/getMemberToTalk.php", {
token: token,
whoToTalkTo: memberID,
})
.then((response) => {
// console.log(response.data);
if (response.data != "Error receiving data") {
let joinedData = [];
response.data.forEach((res) => {
let messages = this.getMessages(res.memberID);
let myMessages = this.getMyMessages(res.memberID);
// console.log(messages);
// console.log(myMessages);
let conversation = [];
let data = {};
setTimeout(() => {
conversation = [...messages, ...myMessages];
conversation.sort(function (a, b) {
return a.date - b.date;
});
// console.log(conversation);
if (conversation.length > 0) {
data = {
memberID: res.memberID,
memberProfileImg: res.memberProfileImg,
memberName: res.memberName,
memberLastname: res.memberLastname,
memberCity: res.memberCity,
memberState: res.memberState,
messages: conversation,
tour: conversation[0].tour,
};
this.isLoading = false;
} else {
this.isLoading = true;
this.getAllMessages();
}
joinedData.push(data);
}, 2000);
});
// console.log(joinedData);
this.memberData = joinedData;
console.log(this.memberData);
} else {
console.log(response.data);
}
})
.catch((error) => {
console.log(error);
});
},
sendMessage: function (memberID, tourID) {
$("#messages_form").on("submit", (e) => {
e.preventDefault();
let message = this.messages;
if (!message.trim()) return;
let postmessage = {
uid: JSON.stringify(this.myID),
memberID: JSON.stringify(memberID),
message: message,
date: Date.now(),
tour: "2",
};
// console.log(message);
this.messages = "";
this.memberData.forEach((res) => {
console.log(res.messages);
if (memberID == res.memberID) res.messages.push(postmessage);
});
console.log(this.memberData);
firebase.firestore().collection('messages').add({
uid: JSON.stringify(this.myID),
memberID: JSON.stringify(memberID),
message: message,
date: Date.now(),
tour: tourID
}).then(res => {
// console.log('Message sent: ' + res.message);
}).catch(e => console.log(e));
});
},
showConversation: function (memberID) {
// console.log(memberID);
// let id = $('.conversation-container').attr('id');
this.memberBox = memberID;
if (this.memberBox == memberID) {
$(".conversation-container").toggle("fast");
}
},
},
mounted() {},
});
I need to get the URL of a picture to show my img :src tag. I tryied:
<img class="card-img-top" :src="noticia.Fotos.Link" alt="Card image cap">
This is my HTML:
<div class="col-lg-4" v-for="noticia in noticias">
<div class="row">
<div class="card mt-3 col-lg-10 offset-lg-1">
<img class="card-img-top" :src="noticia.Fotos.Link" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{noticia.Titulo}}</h5>
<p class="card-text text-center">
{{noticia.Descricao}}
</p>
</div>
</div>
</div>
</div>
This is my script:
<script>
new Vue({
el: '#noticia',
data: {
UnidadeId: "",
Identificador: "",
Tipo: "",
},
data() {
return {
noticias: [],
}
},
mounted() {
var self = this
axios.get('URL', {
params: this.axiosParams
})
.then(response => {
console.log(response);
self.noticias = response.data
})
.catch(error => {
console.log(error);
})
},
computed: {
axiosParams() {
const params = new URLSearchParams();
params.append('UnidadeId', '31');
params.append('Identificador', '0');
params.append('Tipo', '1');
return params;
}
},
})
</script>
The response:
[
{
"ItemId": 902,
"Titulo": "Noticia",
"Descricao": "Noticia",
"Data": "/Date(1590593442191)/",
"QtdeCurtidas": 0,
"QtdeComentarios": 0,
"Curtido": false,
"Observacao": null,
"Fotos": [
{
"FotoId": 1508,
"Link": "http://agro.aloapp.com.br/Imagens/cVV4S0dINGRESm9IN3IxM2swYXVjZz09/Item/bg_carousel_2.jpg"
}
],
"Videos": [],
"IsVideo": false
}
]
You're trying to retrieve an element from an array (not an ArrayList) which means you need to specify which element in the array you want. In Javascript, this works by specifying the index of the element in brackets after the array name. If you want the first element, you can do noticia.Fotos[0].Link.
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 need to render my template templates/page.html:
<section class="section">
<div class="container">
<h1 class="title"><%= title %></h1>
<div><%= content %></div>
<div><%= pages %></div>
</div>
</section>
into my div element with page-content id:
// Underscore mixins
_.mixin({templateFromUrl: function (url, data, settings) {
var templateHtml = "";
this.cache = this.cache || {};
if (this.cache[url]) {
templateHtml = this.cache[url];
} else {
$.ajax({
url: url,
method: "GET",
async: false,
success: function(data) {
templateHtml = data;
}
});
this.cache[url] = templateHtml;
}
return _.template(templateHtml, data, settings);
}});
// Models
var PageState = Backbone.Model.extend({
defaults: {
title: "",
subtitle: "",
content: "",
pages: "",
state: "games"
}
});
var pageState = new PageState();
// Routers
var PageRouter = Backbone.Router.extend({
routes: {
"": "games",
"!/": "games",
"!/games": "games",
"!/users": "users",
"!/add-user": "add_user"
},
games: function () {
select_item($("#games"));
console.log("games");
pageState.set({ state: "games" });
},
users: function () {
select_item($("#users"));
console.log("users");
pageState.set({ state: "users" });
},
add_user: function () {
console.log("add_user");
}
});
var pageRouter = new PageRouter();
// Views
var Page = Backbone.View.extend({
templates: {
"page": _.templateFromUrl("/templates/page.html")
},
initialize: function () {
this.render();
},
render: function () {
var template = this.templates["page"](this.model.toJSON());
this.$el.html(template);
return this;
}
});
$(function () {
var page = new Page({
el: '#page-content',
model: pageState
});
});
// Run backbone.js
Backbone.history.start();
// Close mobile & tablet menu on item click
$('.navbar-item').each(function(e) {
$(this).click(function() {
if($('#navbar-burger-id').hasClass('is-active')) {
$('#navbar-burger-id').removeClass('is-active');
$('#navbar-menu-id').removeClass('is-active');
}
});
});
// Open or Close mobile & tablet menu
$('#navbar-burger-id').click(function () {
if($('#navbar-burger-id').hasClass('is-active')) {
$('#navbar-burger-id').removeClass('is-active');
$('#navbar-menu-id').removeClass('is-active');
} else {
$('#navbar-burger-id').addClass('is-active');
$('#navbar-menu-id').addClass('is-active');
}
});
// Highlights an item in the main menu
function select_item(sender) {
$("a.v-menu-item").removeClass("is-active");
sender.addClass("is-active");
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
<body>
<section class="hero is-primary is-medium">
<div class="hero-head">
<nav id="navMenu" class="navbar">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item is-size-2">Virto</a>
<span id="navbar-burger-id" class="navbar-burger burger" data-target="navbar-menu-id">
<span></span>
<span></span>
<span></span>
</span>
</div>
<div id="navbar-menu-id" class="navbar-menu">
<div class="navbar-end">
<a id="games" href="#!/games" class="navbar-item v-menu-item is-active">Games</a>
<a id="users" href="#!/users" class="navbar-item v-menu-item">Users</a>
<span class="navbar-item">
<a href="#!/add-user" class="button is-primary is-inverted">
<span class="icon">
<i class="fas fa-user-circle"></i>
</span>
<span>Add user</span>
</a>
</span>
<div>
</div>
</div>
</nav>
</div>
</section>
<div id="page-content"></div>
</body>
But my content doesn't load... I'm a noobie in backbone.js still so can someone explain what do I doing wrong and how to fix?
ADDED
I have checked my script in debugger. It loads a template and finds my div in the render() function but I can't see any result in browser after, my div is empty still.
I created a plunker with your code, and it works fine for me: link
I think you only forgot to initialize your model:
// Models
var PageState = Backbone.Model.extend({
defaults: {
title: "Title - 1",
subtitle: "Subtitle - 1",
content: "Content",
pages: "1",
state: "games"
}
});