Access objects property in component - javascript

I'm trying to access email property of user object
{"name":"test", "email":"test#test.x"}
like this:
<input type="text" :placeholder="user.email">
When I try to access property in console -> console.log(user.email) everything work's just fine
component code ->
<template>
<div>
<form method="POST" action="smth.php">
<input type="text" :placeholder="user.email">
</form>
</div>
</template>
<script>
export default {
props: {
user: {
type: Object,
required: true
}
},
}
</script>
Component call ->
<div class="container">
<page-profile :user="{{ $user->toJson() }}"></page-profile>
</div>
Could you please show me the right way how to access the email property of user object?
Both console and npm watch show no errors.

The issue is with this code:
<div class="container">
<page-profile :user="{{ $user->toJson() }}"></page-profile>
</div>
You don't need those curly braces in a property definition. Those are only required in the content of a tag and not an attribute.
I'm also not sure what the -> arrow is supposed to be doing. Is that from PHP?
You probably want something more like the following:
<div class="container">
<page-profile :user="$user.toJson()"></page-profile>
</div>

Related

Add one component multiply times on one page

How can I place same component on one page multiply times? I have input component who get props and do some stuff. I need to place more than one inputs in one page and i thought i can just copy/paste my component but i get error because vue is thinking that all of my components are the same dom element. how can I put them?
index.vue
<template>
<div class="container">
<Input name="name" />
<Input name="surname" />
<Input name="pass" />
</div>
</template>
Input.vue
<template>
<div class="inputs">
<label class="inputs__label" :for="name">Имя</label>
<input
v-click-outside="moveR"
class="inputs__input"
:name="name"
type="text"
#click="moveL($event.target)"
/>
</div>
</template>
<script>
import vClickOutside from 'v-click-outside'
export default {
directives: {
clickOutside: vClickOutside.directive,
},
props: ['name'],
methods: {
moveR(e) {
console.log(e)
e.classList.add('inputs__lable_r')
},
moveL(e) {
console.log(e)
e.classList.remove('inputs__lable_r')
},
},
}
</script>
iam sorry i dont have a big baggage of knowledge of vue and google doesnt gave me needed information
i write on nuxt but i think its same trouble with vue
This is what it should be
moveR(e) {
e.target.classList.add('inputs__lable_r')
},
You were missing a e.target, hence it was not targeting the HTML element but rather the event.

eval() alternative in Meteor to a variable name declaring a Mongo collection

This Meteor code has let Vehicles= new Mongo.Collection('vehicles'); and a html <div id='Vehicles', I like use the <get obj in var named Veh>.find({}).count() the below code works fine but I read to avoid the use of eval(). Reading up on alternatives could not satisfy me to formalize a solution. Please help with a solution or show how to write this in a non eval() way. Thanks
Update: It needs to run on the server "nodeJs" and not in the browser
//cliant/main.js
$('input').on('blur', function(e) {
let collectionVar= $(this).parents('div')[2].id // Vehicles is the same as the collection variable.
console.log(eval(collectionVar).find({}).count()) // works but need an alternative to eval()
})
<template name="Vehicles">
<div id="Vehicles" class="subject-container" >
<div class="section-head">
<div class="control">
<input id="plate" type="text" size="6" placeholder="plate" value={{vehicle.plate}}>
</div>
</div>
</div>
</template>
You should use Template events instead of jQuery event listeners to get the most out of your data during UI events.
You can then easily attach data-* attributes to the component to avoid any parent fiddling:
<template name="Vehicles">
<div id="Vehicles" class="subject-container" >
<div class="section-head">
<div class="control">
<input id="plate"
data-collection="Vehicles" <!-- ref the collection -->
type="text"
size="6"
placeholder="plate"
value={{vehicle.plate}}>
</div>
</div>
</div>
</template>
You can then use either a global Object, that references collecitons by name or dburles:mongo-collection-instances to get the collection by name (I would favour the second, because it does not further pollute the global namespace):
Template.Vehicles.events({
'blur #plate' (event, templateInstance) {
const collectionName = templateInstance.$(event.currentTarget).data('collection')
// wihtout jQuery: = event.currentTarget.getAttribute('data-collection')
const collection = Mongo.Collection.get(collectionName)
}
})
References
https://atmospherejs.com/dburles/mongo-collection-instances
http://blazejs.org/api/templates.html#Event-Maps

Vue.Js(2) : Property or method "hideModel" is not defined on the instance but referenced during render

I have just started to learn VueJs and trying to bind a clickEvent and hide the message <article>. But it show the following warning-
[Vue warn]: Property or method "hideModel" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
Although when i m trying in-line like.
<button type='button' v-on:click='isInvisible=false'>X</button>
It working fine. But with the function it not working.
index.html
<div id="root">
<message title="my-message" body="lorem ipsum sit ben"></message>
<message title="Other message" body="This is other message">
</message>
</div>
<link rel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.css" />
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<script src="main.js"></script>
main.js
Vue.component('message', {
props:['title', 'body'],
data(){
return {
isVisible:true
};
},
template:`<article class="message" v-show='isVisible'>
<div class="message-header">
<p>{{ title }}</p>
<button type='button' v-on:click='hideModel'>X</button>
</div>
<div class="message-body">
{{body}}
</div>
</article>`,
method:{
hideModel(){
this.isVisible=false;
}
}
})
new Vue({
el:"#root",
});
It happens because of mistyping. All methods should be placed into the methods. Don't forget about s in the end.
...
methods:{
hideModel(){
this.isVisible=false;
}
}
...
rename method to methods and you should be fine. You can add any arbitrary number of keys to the Vue component constructor object, but they will only be picked up by Vue if they correspond to the the known properties. Hence 'method' will be ignored, whereas 'methods' will work.

How come my audio tag loads the source when it is hard coded, but not when provided by Vue.js?

I've created a component, and in that component is an audio tag. I've been trying to pass the file path of the mp3 to the component from its parent, but the audio element doesn't seem to be able to load the file successfully for some reason. The element just ends up greyed out, and I don't get any kind of error. I know the properties are being passed successfully because I'm also passing in the title of the track, and that loads just fine in the component. However, if I hardcode the same path in for the source, then it works fine. Which isn't a big deal, but I have 11 tracks to do and it would be much easier with a v-for statement.
Here's my parent component:
<template>
<div container>
<div class=banner>
<img src="../assets/CryptoLogo2.svg"/>
</div>
<div class="albumcontainer">
<div class="covercontainer"><img src="../assets/TIADCover(Final).png"/></div>
<div class="arrow"></div>
<div class="tracklistcontainer">
<table class="tracklist">
<tr class="track" v-for="track in tracks" :key="track.file" style="padding: 20px;">
<td>
<player :name="track.name" :file="track.file" />
</td>
</tr>
</table>
</div>
</div>
<div class="bio">
<p>
</p>
</div>
<div class="footer">
<div class="footericons">
<img src="../assets/icons/Facebook.svg" />
<img src="../assets/icons/Instagram.svg" />
<img src="../assets/icons/Twitter.svg" />
</div>
</div>
</div>
</template>
<script>
import player from './player'
export default {
name: "Album1",
data() {
return {
tracks: [
{
name: '5G',
file: '../assets/tracks/5G.mp3'
}
]
}
},
components:{
player
}
};
</script>
And then the component with the audio tag:
<template>
<div>
<h3>{{ name }}</h3>
<audio controls controlsList="nodownload">
<source ref="player" v-bind:src="file" type="audio/mpeg">
</audio>
</div>
</template>
<script>
export default{
name: "player",
props: {
name: {
type: String,
default: null
},
file:{
type: String,
default: null
}
}
}
</script>
Here you can see that my data is being passed successfully.
And you see that the source attribute is being loaded correctly as well.
This is what I get, and you can see the h3 loads fine, so I know the data is being passed. But the element is greyed out.
To test it out, I tried just hard coding the file path:
<source src="../assets/tracks/5G.mp3">
And that works just fine:
But I don't want to do it like that because I have about 11 tracks to do, so I would like for it to load from the data being passed so that I can reuse the component. Any ideas?
try using something like this in your Vue v-for I use this when src is not loading on the img tag.
:src="getSrc(x.src)"
methods: {
getSrc(src) {
return require("../assets/" + src);
}
}
Your watch function on file prop is never triggered because your file name is static, it never triggers a change on the watcher, before mounting the component, at least in the code you provided it is that way.
From Vue.js API vm.$watch
Watch an expression or a computed function on the Vue instance for changes. The callback gets called with the new value and the old value.

Execute a method when image is loaded

I've been trying to execute a method when a image has fully loaded, but it simply throws an error that my function doesn't exists:
Uncaught ReferenceError: imageLoaded is not defined
at HTMLImageElement.onload (projetos:1)
Here's my code:
<template>
<div class="card">
<h2>{{projeto.nome}}</h2>
<div class="row">
<div class="col-sm-10 col-sm-offset-1" id="img-container">
<img :src="projeto.foto" :alt="projeto.nome" onload="imageLoaded()">
<div class="row" id="info">
<div class="col-xs-6">Conclusão: {{projeto.duracao}}</div>
<div class="col-xs-6">Projeto realizado em {{projeto.ano}}</div>
<br><br>
<p>{{projeto.descricao}}</p>
</div>
</div>
</div>
</div>
</template>
<script>
import { eventBus } from "../../main";
export default {
props: ["projeto"],
methods: {
imageLoaded() { // the function i want to execute
eventBus.loading(false);
}
}
};
</script>
I've tried using :load="" (wich i discovered that doesn't exists) and placing a function outside my export default scope. Since my images are in a v-for i think onload is the best way of achieving this.
So is there a better way? How can i do this? Is there a directive i can use? Am i doing something wrong?
Use the v-on directive or the shorthand # for listening for DOM events like you would do for example with #click="" - so #load="imageLoaded()" should work.

Categories