Vue.js export default not working - vue.js

I'm following the form example and it doesn't work ::
https://bootstrap-vue.js.org/docs/components/form
This is my code, inside my simple basic index.html :
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.css"/>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/babel-polyfill#latest/dist/polyfill.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.js"></script>
</head>
<body>
<template>
<div>
<b-form #submit="onSubmit" #reset="onReset" v-if="show">
<b-form-group id="exampleInputGroup1"
label="Email address:"
label-for="exampleInput1"
description="We'll never share your email with anyone else.">
<b-form-input id="exampleInput1"
type="email"
v-model="form.email"
required
placeholder="Enter email">
</b-form-input>
</b-form-group>
<b-form-group id="exampleInputGroup2"
label="Your Name:"
label-for="exampleInput2">
<b-form-input id="exampleInput2"
type="text"
v-model="form.name"
required
placeholder="Enter name">
</b-form-input>
</b-form-group>
<b-form-group id="exampleInputGroup3"
label="Food:"
label-for="exampleInput3">
<b-form-select id="exampleInput3"
:options="foods"
required
v-model="form.food">
</b-form-select>
</b-form-group>
<b-form-group id="exampleGroup4">
<b-form-checkbox-group v-model="form.checked" id="exampleChecks">
<b-form-checkbox value="me">Check me out</b-form-checkbox>
<b-form-checkbox value="that">Check that out</b-form-checkbox>
</b-form-checkbox-group>
</b-form-group>
<b-button type="submit" variant="primary">Submit</b-button>
<b-button type="reset" variant="danger">Reset</b-button>
</b-form>
</div>
</template>
</body>
and the js code +1
<script>
export default {
data () {
return {
form: {
email: '',
name: '',
food: null,
checked: []
},
foods: [
{ text: 'Select One', value: null },
'Carrots', 'Beans', 'Tomatoes', 'Corn'
],
show: true
}
},
methods: {
onSubmit (evt) {
evt.preventDefault();
alert(JSON.stringify(this.form));
},
onReset (evt) {
evt.preventDefault();
/* Reset our form values */
this.form.email = '';
this.form.name = '';
this.form.food = null;
this.form.checked = [];
/* Trick to reset/clear native browser form validation state */
this.show = false;
this.$nextTick(() => { this.show = true });
}
}
}
</script>
It is stricly the same than on the vue bootstrap website and it doesnt work
There is a blank screen, and This is the firefox error :
SyntaxError: export declarations may only appear at top level of a module
I can't show my form, there is nothing, just a blank screen, it doesn't work !
Note : i dont wanna to use babel or whatever complex stuff, i simply need my index.html to work
Please help me thank you

The example you copied verbatim is the contents of a Vue Single File Component. Those need either Webpack or Browserify to be translated to actual JavaScript that the browser can understand.
You can re-write the code avoiding the SFC structure, using Vue.component() and pass the template in the template property, if you want to obtain a reusable Vue component, but it will be a bit more complex.
Otherwise, if it is only a single page, simply use new Vue() and bind to an element selection using the el property (see Declarative Rendering in the guide):
var app = new Vue({
el: '#app',
data: {
...
}
})
and inside your html:
<div id="app">
...
... vue perform rendering and interpolation here ...
...
</div>

You are confusing Single-File Components with using Vue in simple HTML files.
To get the latter you could do as shown below.
Basically you have to:
Remove the <template> tag and add an id to its inner div, such as: <div id="app">
Wrap the object that was being exported in a Vue constructor and add an el option to it:
<script>
new Vue({
el: '#app',
data() {
JSBin demo here.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.css"/>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/babel-polyfill#latest/dist/polyfill.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.js"></script>
</head>
<body>
<div id="app">
<b-form #submit="onSubmit" #reset="onReset" v-if="show">
<b-form-group id="exampleInputGroup1"
label="Email address:"
label-for="exampleInput1"
description="We'll never share your email with anyone else.">
<b-form-input id="exampleInput1"
type="email"
v-model="form.email"
required
placeholder="Enter email">
</b-form-input>
</b-form-group>
<b-form-group id="exampleInputGroup2"
label="Your Name:"
label-for="exampleInput2">
<b-form-input id="exampleInput2"
type="text"
v-model="form.name"
required
placeholder="Enter name">
</b-form-input>
</b-form-group>
<b-form-group id="exampleInputGroup3"
label="Food:"
label-for="exampleInput3">
<b-form-select id="exampleInput3"
:options="foods"
required
v-model="form.food">
</b-form-select>
</b-form-group>
<b-form-group id="exampleGroup4">
<b-form-checkbox-group v-model="form.checked" id="exampleChecks">
<b-form-checkbox value="me">Check me out</b-form-checkbox>
<b-form-checkbox value="that">Check that out</b-form-checkbox>
</b-form-checkbox-group>
</b-form-group>
<b-button type="submit" variant="primary">Submit</b-button>
<b-button type="reset" variant="danger">Reset</b-button>
</b-form>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
form: {
email: '',
name: '',
food: null,
checked: []
},
foods: [
{text: 'Select One', value: null},
'Carrots', 'Beans', 'Tomatoes', 'Corn'
],
show: true
}
},
methods: {
onSubmit(evt) {
evt.preventDefault();
alert(JSON.stringify(this.form));
},
onReset(evt) {
evt.preventDefault();
/* Reset our form values */
this.form.email = '';
this.form.name = '';
this.form.food = null;
this.form.checked = [];
/* Trick to reset/clear native browser form validation state */
this.show = false;
this.$nextTick(() => {
this.show = true
});
}
}
});
</script>
</body>
</html>
The above uses your code directly in the Vue instance.
If you want to use your form as a component, such as:
<div id="app">
<my-form></my-form>
</div>
Follow this JSBin demo.

Related

b-input model has value of type string

I am trying to create a form with a number field.
<b-input v-model="testNumber" type="number"/>
On my data, I have a simple number var.
data() {
return {
testNumber: 10,
}
},
However when I trace testNumber it is a string
{{ typeof testNumber }} // String
You can add a modifier to the v-model.
(https://v2.vuejs.org/v2/guide/forms.html#number)
<b-form-input v-model.number="testNumber" />
UPDATE
Don't use the v-model.number this as bootstrap-vue recommens not to do so:
v-model modifiers .number and .trim can cause unexpected cursor jumps
when the user is typing (this is a Vue issue with v-model on custom
components). Avoid using these modifiers.
But use as b-form-input suggests:
To get around this, <b-form-input> and <b-form-textarea> have two
boolean props trim and number which emulate the native Vue v-model
modifiers .trim and .number respectively.
<b-form-input v-model="testNumber" :number="true" />
The type=number default return value type is string. you can see here HTML input elements are documented to return string representing a number
For changing this behavior of model value, you need to convert the your value when input is changing. Like below example
Please below code snippet :
new Vue({
el: '#app',
data() {
return {
number:10,
testNumber:100
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="number" type="number"/>
<p>type of number : {{typeof number}}</p>
<input v-model="testNumber" type="number" #input="e => testNumber = +e.target.value" />
<p>type of testNumber: {{typeof testNumber}}</p>
</div>
Bootstrap-vue example
In this example, you can use value by getting .valueAsNumber and same as above you can use +.value.
new Vue({
el: '#app',
methods: {
updateVm(e) {
this.testNumber1 = e.target.valueAsNumber;
}
},
data() {
return {
number: null,
testNumber: null,
testNumber1: null
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<!-- Add this to <head> -->
<!-- Load required Bootstrap and BootstrapVue CSS -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<!-- Load polyfills to support older browsers -->
<script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue#latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<div id="app" style="padding:10px;">
<template>
<b-container fluid>
<b-row>
<b-col><b-input placeholder="First number" v-model="number" type="number"/></b-col>
<b-col>{{typeof number}}</b-col>
</b-row>
<b-row>
<b-col><b-input placeholder="2nd number" v-model="testNumber" type="number" v-on:input="$v => testNumber = +$v"/></b-col>
<b-col>{{typeof testNumber}}</b-col>
</b-row>
<b-row>
<b-col><b-input placeholder="3rd number" v-model="testNumber1" type="number" v-on:input="updateVm(event)"/></b-col>
<b-col>{{typeof testNumber1}}</b-col>
</b-row>
</b-container>
</template>
</div>
<template>
<b-container fluid>
<b-row class="my-1" v-for="type in types" :key="type">
<b-col sm="3">
<label :for="`type-${type}`">Type <code>{{ type }}</code>:</label>
</b-col>
<b-col sm="9">
<b-form-input :id="`type-${type}`" :type="type"></b-form-input>
</b-col>
</b-row>
</b-container>
</template>
<script>
export default {
data() {
return {
types: [
'number'
]
}
}
}
</script>

How to bind v-model from input in one div to another div or component

I have my input field in one div, and will have label in another div (as sidebar in my application). I want to update label in sidebar, as I type in input on first div.
I am happy to create second div a component if that's the way. I was reading online, and it was said we could use props to pass data to component. But I am not able to link input field to component. Please find my code as below:
var app = new Vue({
el: '#div1',
data: {
message: ''
}
})
Vue.component('testp', {
props: ['message'],
template: '<p>Message is: {{ message }}</p>'
})
var div2 = new Vue({
el: '#div2'
});
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="div1">
<input v-model="message" placeholder="edit me">
</div>
<div id="div2">
<testp></testp>
</div>
</body>
</html>
As Pointed in Comment You have no reason to have two separate Vue instance and the First Answer is correct. But in some cases where you really need to have multiple Vue instances, you can actually use them in the following manner.
var app = new Vue({
el: '#div1',
data: {
message: ''
}
})
Vue.component('testp', {
props: ['message'],
template: '<p>Message is: {{ message }}</p>'
})
var div2 = new Vue({
el: '#div2',
computed: {
newMessage() {
return app.message;
}
},
});
Html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="div1">
<input v-model="message" placeholder="edit me">
</div>
<div id="div2">
<testp :message="newMessage"></testp>
</div>
</body>
</html>
Please observe the computed value newMessage is actually getting its value form a different Vue instance (app) and it is also reactive. Therefore whenever the value in first Vue instance changes, it is updated in another Vue instance.
Codepen: https://codepen.io/ashwinbande/pen/xMgQQz
Like I have pointed out in my comments, there is no reason for you to use two separate Vue instances. What you can do is simply wrap everything within an app container, e.g. <div id="#app">, and then instantiate your VueJS instance on that element instead.
Then, you can use v-bind:message="message" on the <testp> component to pass in the message from the parent. In this sense #div1 and #div2 are used entirely for markup/decorative purposes and are not used as VueJS app containers in your code.
Vue.component('testp', {
props: ['message'],
template: '<p>Message is: {{ message }}</p>'
});
var app = new Vue({
el: '#app',
data: {
message: ''
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<div id="div1">
<input v-model="message" placeholder="edit me">
</div>
<div id="div2">
<testp v-bind:message="message"></testp>
</div>
</div>

I have some question about Vue component structure

While studying Vue By self-taught, I faced some problem.
First, I bind some component by new Vue ({el:" # id "}).
And when I bind root component <div id = "app"> by new Vue ({el:" # app "}),
It ruin what already was binding there.
My function and data in new Vue ({el:" # id "}) didn't work anymore.
Am I doing the wrong design?
If so, how should I approach the problem?
<html>
<head>
<script src="https://unpkg.com/vue#2.5.17/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div id="comp-a">
<input type="text" v-model="message"/>
{{message}}
</div>
</div>
</body>
<script>
new Vue({
el : "#comp-a",
data : {
message : "message"
}
})
new Vue({
el : "#app"
})
</script>
You can use component.
reference: https://v2.vuejs.org/v2/guide/components.html
let comp_a=Vue.component('comp-a', {
data: function () {
return {
message: ""
}
},
template: ` <div><input type="text" v-model="message"/>
{{message}}</div>`
});
let app = new Vue({
el:"#app"
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<comp-a></comp-a>
</div>
If you want to component's html code in html area. template can point to by id. you can do following:
let comp_a=Vue.component('comp-a', {
data: function () {
return {
message: ""
}
},
template: "#comp-a"
});
let app = new Vue({
el:"#app"
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<comp-a></comp-a>
</div>
<template id="comp-a">
<div>
<input type="text" v-model="message"/>
{{message}}
</div>
</template>
VueJS does not work this way. You don't nest IDs. You could do this:
<html>
<head>
<script src="https://unpkg.com/vue#2.5.17/dist/vue.js"></script>
</head>
<body>
<div id="app">
</div>
<div id="comp-a">
{{message}}
</div>
</body>
<script>
new Vue({
el : "#app"
})
new Vue({
el : "#comp-a",
data : {
message : "message"
}
})
</script>
But even that approach has problems. You really should have only one matching VueJS area.
The only reason to have two is if you really have two applications running on the same html file. I have never seen a reason to do that.

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

Property Binding & Sync in vue.js

I'm having trouble syncing my properties in vue.js, I have an 'active' property that I want to set to the value of each instance 'plan', but at the same time I would like to sync the property with the parent, with no luck. What am I doing wrong ?
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Vue</title>
<link rel="stylesheet prefetch" href="http://bootswatch.com/paper/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>
</head>
<body>
<div class="container">
<div id="app">
<pre>
#{{ $data | json}}
</pre>
<div v-for="plan in plans">
<plan :active.sync="active" :plan.sync="plan"></plan>
</div>
</div>
</div>
<template id="plan_template">
<div>
<span >#{{ plan.name }}</span>
<span >#{{ plan.price }}/month</span>
<button #click="setActivePlan" class="btn btn-primary btn-xs">UPGRADE</button>
</div>
</template>
<script>
new Vue({
el:'#app',
data:{
plans:[
{name:'Executive',price:100},
{name:'Professional',price:50},
{name:'Personal',price:30},
{name:'Free',price:0}
],
active:{},
},
components:{
plan:{
template:'#plan_template',
props:['plan', 'active'],
methods:{
setActivePlan:function(){
this.active=this.plan;
}
}
}
}
});
</script>
</body>
</html>
Note: This answer applies to V2 of Vue JS, < 2.3.0.
If you are using up V2.3.0+ then you can use .sync and .once modifiers: documentation here
You are using version 2 of Vue. The .sync and .once modifiers have been removed. From the docs:
Props are now always one-way down. To produce side effects in the parent scope, a component needs to explicitly emit an event instead of relying on implicit binding.
I have modified your code to use events here:
new Vue({
el:'#app',
data:{
plans:[
{name:'Executive',price:100},
{name:'Professional',price:50},
{name:'Personal',price:30},
{name:'Free',price:0}
],
active:{},
},
methods: {
setActivePlan: function(plan) {
this.active = plan;
}
},
components:{
plan:{
template:'#plan_template',
props:['plan', 'active'],
methods:{
setActivePlan:function(){
// emit an event to the parent indicating that this is the active plan
this.$emit('activate-plan');
}
}
}
}
});
<link rel="stylesheet prefetch" href="http://bootswatch.com/paper/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>
<div class="container">
<div id="app">
<div v-for="plan in plans">
<plan :plan="plan"
:active="active"
#activate-plan="setActivePlan(plan)"
>
</plan>
</div>
<pre>
{{ JSON.stringify($data, null, 2) }}
</pre>
</div>
</div>
<template id="plan_template">
<div>
<span >{{ plan.name }}</span>
<span >{{ plan.price }}/month</span>
<button #click="setActivePlan" class="btn btn-primary btn-xs">UPGRADE</button>
</div>
</template>