Vuejs Axios data not showing - vue.js

The problem of not showing information is delayed in fetching , i need any help for this problem.
<h1>#{{message}}</h1>
<div class="panel panel-primary">
<div class="panel-heading">
<div class="row">
<div class="col-md-10"><h3 class="panel-title">Experience</h3></div>
<div class="col-md-2 text-right">
<button class="btn btn-success">Ajouter</button>
</div>
</div>
</div>
<div class="panel-body" >
<ul class="list-group">
<li class="list-group-item" v-for="experience in experiences" >
<div class="pull-right">
<button class="btn btn-warning btn-sm">Editer</button>
</div>
<h3>#{{experience.titre}}</h3>
<p>#{{experience.body}}</p>
<small>#{{experience.debut}} - #{{experience.fin}}</small>
</li>
</ul>
</div>
</div>
Vuejs
<script src="{{asset('js/vue.js')}}"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Nawfal Kharbouch',
experiences:[]
},
methods:{
getExperiences:function(){
axios.get('http://localhost:8080/getexperiences').then(response=>{
this.experiences=response.data;
console.log(this.experiences);
}).catch(function(error){
console.log('erros : ',error);
})
}
},
mounted:function(){
this.getExperiences();
console.log(this.experiences);
}
})
</script>
The problem of not showing information is delayed in fetching , i need any help for this problem.
//console Google Chrome
[__ob__: Observer]
vue.js:8553 You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html
backend.js:1 vue-devtools Detected Vue v2.5.16
5:171 (3) [{…}, {…}, {…}, __ob__: Observer];
//picture view vide

Instead of using this directly you need to pass it to a variable.
methods:{
getExperiences:function(){
var vm = this
axios.get('http://localhost:8080/getexperiences').then(response=>{
vm.experiences=response.data;
console.log(vm.experiences);
}).catch(function(error){
console.log('erros : ',error);
})
}
},

You can not pass "this" inside a promise, you need to add "this" to a variable.
Exemple:
var app = new Vue({
el: '#app',
data: {
message: 'Nawfal Kharbouch',
experiences:[]
},
methods:{
var self = this;
getExperiences:function(){
axios.get('http://localhost:8080/getexperiences').then(response=>{
self.experiences=response.data;
console.log(self.experiences);
}).catch(function(error){
console.log('erros : ',error);
})
}
},
mounted:function(){
this.getExperiences();
console.log(this.experiences);
}
})

Related

Conditional a href in Vuejs

I am rendering a list of store titles in VueJS, some of them have a url property, some of them don't. If the title has a url, I want to add a a href property:
<div v-for="(store, index) in stores">
<span v-if="store.link"><a :href="store.link" target="_blank">{{ store.title }}</a></span>
<span v-else="store.link">{{ store.title }}</span>
</div>
This works, but the code looks duplicated. Is there anyway to simplify the code further?
you can use component tag:
var app = new Vue({
el: '#app',
data () {
return {
stores: [
{title:'product1',link:'/products/222'},
{title:'product2'},
{title:'product3',link:'/products/333'},
{title:'product4'}
]
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<div v-for="(store, index) in stores">
<component :is="store.link?'a':'span'" :href="store.link || ''" target="_blank">{{store.title}}
</component>
</div>
</div>
I'd remove the first span element, as it's not necessary. Also, the v-else does not need the conditional statement (it's not v-else-if):
new Vue({
el: '#app',
data: {
stores: [
{ link: 'foo', title: 'foo-text' },
{ title: 'bar-text' }
]
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div v-for="(store, index) in stores" :key="index">
<a v-if="store.link" :href="store.link" target="_blank">{{ store.title }}</a>
<span v-else>{{ store.title }}</span>
</div>
</div>
You can use dynamic arguments in vue3
https://v3.vuejs.org/guide/template-syntax.html#dynamic-arguments
<a v-bind:[attributeName]="url"> ... </a>
or binding an object of attributes
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>

Vue.js pass props to dynamicly change component class

I'm trying to learn Vue and encountered this problem.
Vue.component('alert', {
props: ['type', 'bold', 'msg'], template: '<div class="alert alert-{{ type }}" role="alert"><b>{{ bold }}</b> {{ msg }}</div>'
});
var componentProps=new Vue( {
el: '#app',
}
);
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<div id="app" class="container">
<alert type="info" bold="Greetings." msg="This is some information."></alert>
<alert type="warning" bold="Slow down." msg="You might crash."></alert>
<alert type="danger" bold="Oh no!" msg="The program just crashed!"></alert>
<alert type="success" bold="Rock Out" msg="with your Props out!"></alert>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
This is in the output in the inspector.As you can see the props[type] is not changed there.
<div role="alert" class="alert alert-{{ type }}'"><b>Slow down.</b> You might crash.</div>
Link to codepen => https://codepen.io/dakata911/pen/XEKbyq?editors=1010
In vue 2 you can't use interpolations in attributes anymore. You have several possible syntaxes for class and style bindings now. In your specific case you can use:
<div class="alert" :class="'alert-' + type" role="alert">
Demo below.
new Vue({
el: '#app',
data: {
type: 'warning'
}
})
.alert { background: yellow; }
.alert-warning { color: red }
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div class="alert" :class="'alert-' + type" role="alert"> Warning! </div>
</div>
On attributes interpolation doesn't work, you can use : to bind
:class="type"
or
:class="[ type, other, ... ]"
or
:class="{ 'someClass': true, 'other-class': false, 'another': method() }"
And you can have both :class="..." attributes and class="normal class attribute" on the same element/tag

captcha form validation required error message in vue-recaptcha

I am following this Package in vue.js and Laravel 5.6.7 to implement captcha.
https://github.com/DanSnow/vue-recaptcha#install
Component code in vue.js
<template>
<div>
<vue-recaptcha v-model="loginForm.recaptcha"
sitekey="My key">
</vue-recaptcha>
<button type="button" class="btn btn-primary">
Login
</button>
</div>
</template>
<script>
</script>
app.js code
import VueRecaptcha from 'vue-recaptcha';
Vue.use(VeeValidate);
Vue.component('vue-recaptcha', VueRecaptcha);
Question:
Is there any property for vue-recaptcha called required which can be passed to show the form validation message?
You can use a property (loginForm.recaptchaVerified below) to track if the recaptcha was verified and prevent submit + display a message if not:
JSFiddle demo: https://jsfiddle.net/acdcjunior/o7aca7sn/3/
Code below:
Vue.component('vue-recaptcha', VueRecaptcha);
new Vue({
el: '#app',
data: {
loginForm: {
recaptchaVerified: false,
pleaseTickRecaptchaMessage: ''
}
},
methods: {
markRecaptchaAsVerified(response) {
this.loginForm.pleaseTickRecaptchaMessage = '';
this.loginForm.recaptchaVerified = true;
},
checkIfRecaptchaVerified() {
if (!this.loginForm.recaptchaVerified) {
this.loginForm.pleaseTickRecaptchaMessage = 'Please tick recaptcha.';
return true; // prevent form from submitting
}
alert('form would be posted!');
}
}
})
<script src="https://www.google.com/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit" async defer>
</script>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-recaptcha#latest/dist/vue-recaptcha.js"></script>
<div id="app">
<form v-on:submit.prevent="checkIfRecaptchaVerified">
<div>
<vue-recaptcha #verify="markRecaptchaAsVerified"
sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-">
</vue-recaptcha>
</div>
Some other fields of the form here...
<br>
<button>Submit form</button>
<hr>
<div><strong>{{ loginForm.pleaseTickRecaptchaMessage }}</strong></div>
</form>
</div>

Any easier way to access nested object properties in Vue template?

It's convenient to group data into nested object properties. By doing this, we don't have to collect properties from the data field into an entity for later use. As in the following example,
var demo = new Vue({
el: '#demo',
data: {
level1: {
level2: {
level3_1: 'Hello',
level3_2: 'world'
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="demo">
<div class="person">
<h3>{{ level1.level2.level3_1 }}</h3>
<p>{{ level1.level2.level3_2 }}</p>
</div>
</div>
However, it's really overkill having to type the "level1.level2" prefix in order to get to the level3_x field. It'll be very cumbersome if there're loads of level3 fields.
I wonder if there is any way that I can save the work for typing level1.level2 over and over again. Does the template have any syntax so that some section is under the scope of "level1.level2"? Does Vue provide any support so that in this case the prefix "level1.level2" is assumed?
There are a couple of options.
1. Use v-for
Everything inside the v-for block is scoped to the level that you're iterating over. Do it like this:
var demo = new Vue({
el: '#demo',
data: {
level1: {
level2: {
level3_1: 'Hello',
level3_2: 'world'
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="demo">
<div class="person">
<template v-for="(l2prop, l2propName) in level1">
<h3>{{ l2prop.level3_1 }}</h3>
<p>{{ l2prop.level3_2 }}</p>
</template>
</div>
</div>
2. Use a component
Components get a subset of their parent's data, so they're automatically scoped. Do it like this:
Vue.component( "person", {
props: ['data'],
template: '<div class="person"><h3>{{ data.level3_1 }}</h3><p>{{ data.level3_2 }}</p></div>'
});
var demo = new Vue({
el: '#demo',
data: {
level1: {
level2: {
level3_1: 'Hello',
level3_2: 'world'
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="demo">
<person v-bind:data="level1.level2"></person>
</div>
The example of #jason-smith is almost right. v-for is used for arrays or lists. To make it work is necessary to put your object in list.
Following his example the better approach would be
var demo = new Vue({
el: '#demo',
data: {
level1: {
level2: {
level3_1: 'Level 3_1',
level3_2: 'Level 3_2'
}
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<div class="person">
<template v-for="level2Obj in [level1.level2]">
<h3>{{ level2Obj.level3_1 }}</h3>
<p>{{ level2Obj.level3_2 }}</p>
</template>
</div>
</div>
There are serval ways:
Use a method that gets the same level
methods:{
getLvl3: function(nr){
return this["level"+nr]["level"+nr]["level3_"+nr];
}
{{ getLvl3(1) }}
Iterate over with v-for v-for docu
example:
<div id="demo">
<div class="person">
<template v-for="(lvl2, key) in level1">
<template v-for="(lvl3, key) in lvl2">
<h3 v-if="key === 'level3_1'>{{ lvl3 }}</h3>
<p v-if="key === 'level3_2'">{{ lvl3 }}</p>
</template>
</template>
</div>
</div>
bind to variable that is defined outside of vue:
var nested = { level1: { level2: { level3_1: 'Hello', level3_2: 'world' }}
and inside of vue component or instance:
data:{
level2: nested.level1.level2,
}
<div id="demo">
<div class="person">
<h3>{{ level2.level3_1 }}</h3>
<p>{{ level2.level3_2 }}</p>
</div>
</div>

When one of the data attributes of Vue will change, Vue will re-execute all instruction operations

I just want to change the value of msg,but all the instruction(v-for,v-text,v-bind) of the Vue will re-execute . How to solve this problem?
<div class="container">
<div id="app">
<div v-for="item in list">
<div> {{item.name}} </div>
<div>{{Math.random()}}</div>
</div>
<div>{{Math.random()}}</div>
<div>{{msg}}</div>
<input type="text" v-model='msg'>
</div>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
list: [{ name: "I am Tom" }, { name: "I am Mary" }],
msg: "hello"
}
})
</script>
Because you embedded Math.random() in the template for the VUe, every time the DOM for the Vue needs to be updated (as in when you change msg), a new value will be calculated. One way you might solve this is to initialize the random value when the Vue is created.
var app = new Vue({
el: "#app",
data: {
list: [{ name: "I am Tom" }, { name: "I am Mary" }],
msg: "hello",
random: Math.random()
}
})
And then use the initialized value in your template.
<div id="app">
<div v-for="item in list">
<div> {{item.name}} </div>
<div>{{random}}</div>
</div>
<div>{{random}}</div>
<div>{{msg}}</div>
<input type="text" v-model='msg'>
</div>
Another way you might solve the issue is to isolate the changes to msg in their own scope (a component).
Vue.component("message", {
props:["msg"],
template:`
<div>
<div>{{internalMessage}}</div>
<input type="text" v-model='internalMessage'>
</div>
`,
data(){
return {
internalMessage: this.msg
}
}
})
var app2 = new Vue({
el: "#app2",
data: {
list: [{ name: "I am Tom" }, { name: "I am Mary" }],
msg: "hello",
}
})
And the template:
<div id="app2">
<div v-for="item in list">
<div> {{item.name}} </div>
<div>{{Math.random()}}</div>
</div>
<div>{{Math.random()}}</div>
<message :msg="msg"></message>
</div>
Here is an example of both approaches.