okay. complete retool since people kept getting bogged down in things not related to the question. so i've boiled it down the the smallest essence:
<script src='_js/vue.2.6.11.js'></script>
<div id="app">
<h1>{{ email }}</h1>
<h1>{{ email[reportID] }}</h1>
<hr>
<button #click='makeItGo'>CLICK</button>
</div>
<script>
var vm = new Vue ({
el: '#app',
data: {
email: [],
reportID: 40,
info: 'this is info',
},
methods: {
makeItGo() {
vm.email.push(vm.reportID);
vm.email[reportID] = info; <-- this doesn't work. WHY?
vm.email[reportID].push(info); <-- this doesn't work either. WHY?
}
},
});
</script>
this will generate the following errors:
[Vue warn]: Error in v-on handler: "ReferenceError: reportID is not defined"
(found in <Root>)
ReferenceError: "reportID is not defined"
makeItGo http://localhost/project/test.php line 669 > scriptElement:27
invokeWithErrorHandling http://localhost/project/_js/vue.2.6.11.js line 669 > scriptElement:1863
invoker http://localhost/project/_js/vue.2.6.11.js line 669 > scriptElement:2188
_wrapper http://localhost/project/_js/vue.2.6.11.js line 669 > scriptElement:7547
here's the frustration: WHY does it state that 'reportID' is undefined when it so obviously is. and WHY does calling it directly (vm.email vs email) not bypass any scoping issues as i would expect it (which is what appears to be the problem)? in PHP, this just doesn't happen so i'm confused.
all i'm trying to do is dynamically build a nested array. from there, a short hop to making it associative... i hope.
email
└ 40
└ 'this is info'
Hoist this at the top of your method
let that = this;
and then use that throughout your method instead of this. That way your preserve the scope in each method.
Related
I have a form in my Vue component which uploads the api file. Now I want to render the contents of the file like this:
I have imported swagger client library: https://github.com/swagger-api/swagger-ui.
Now, here
is an example of how you do it in a static page. But I need to do it inside a Vue component (or Quasar, specifically), so I do it like that:
Register swagger-ui inside my register components file:
<link rel="stylesheet" type="text/css" href="swagger-ui.css">
Now it is available as:
this.swaggerUI({})
anywhere in my components. Inside my component I have a div in a template to render the api file:
<template>
<q-form>here lies q-file element, submit button and other stuff</q-form>
<div id="swagger-ui"></div>
</template>
In the mentioned question he had something like:
<script>
window.onload = function() {
const ui = SwaggerUIBundle({
url: "https://yourserver.com/path/to/swagger.json",
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
]
})
window.ui = ui
}
</script>
Here's the difference: first of all, no window.onload, I must render it on submit button. Then, I deal with an uploaded file stored in my model, so no URL here. Now, I don't get how to make it work with locally stored file, when I try with the remote url, it gives me:
vue.esm.js?a026:628 [Vue warn]: Error in v-on handler: "Invariant Violation: _registerComponent(...): Target container is not a DOM element."
I was getting a similar error (Target container is not a DOM element) trying to use a static swagger spec. Instead of using window.onload, I found that Vue has the mounted() function, so this Vue 3 file worked for me:
<template>
<div class="swagger" id="swagger"></div>
</template>
<script>
import SwaggerUI from 'swagger-ui';
import 'swagger-ui/dist/swagger-ui.css';
export default {
name: "Swagger",
mounted() {
const spec = require('../path/to/my/spec.json');
SwaggerUI({
spec: spec,
dom_id: '#swagger'
})
}
}
</script>
This one appeared to be a simple yet very unobvious typo: in windows.onload function:
dom_id: '#swagger-ui',
must instead be
dom_id: 'swagger-ui',
without hash sign, that's it!
Basically what I want to do is to pass variable from flask to vue.js, but nothing seems to be working. So far I've tried a lot of options and suggested idea from JavaScript raises SyntaxError with data rendered in Jinja template but my problem is still here. Exactly what I'm trying to do is when passed argument d_var from flask, I want it to be displayed on html(title_variable) using vue.js.
VUE.JS CODE
var app = new Vue({
el: "#app",
delimiters : ['[[', ']]'],
data: {
message: "Hello vue! (a dynamic thing)",
title_variable = {{d_var}},
indication true,
j: "You should work harder"
}
HTML
<div id="app">
<p>
{{ message }}
</p>
<p>
<span v-bind:title="title_variable">
Show me some text...
</span>
</p>
</div>
FLASK
from flask import Flask, Response, jsonify, request, flash,
render_template,
import os
import json
app = Flask(__name__)
#app.route("/")
def home():
d_var = 'ahahahah'
return render_template("index.html", title_variable=d_var)
if __name__=="__main__":
app.secret_key=os.urandom(12)
app.run(debug=True,host='0.0.0.0',port=5000)
Several problems here...
You've set your Vue delimiters to use [[...]] so you should use
[[ message ]]
in your Vue template
Flask is passing d_var to index.html as title_variable so that's what you should use within {{...}}, not d_var
Your JavaScript data object isn't valid. You should not be using = to assign property values. Try this instead
var app = new Vue({
el: "#app",
delimiters : ['[[', ']]'],
data: {
message: "Hello vue! (a dynamic thing)",
title_variable: {{ title_variable|tojson }},
indication: true,
j: "You should work harder"
}
})
See here for information on the tojson() filter ~ https://flask.palletsprojects.com/en/1.1.x/templating/#standard-filters
I'm a newbie to both these frameworks and the first thing I found is a conflict. So because the double curly brackets are reserved by Tornado, I changed the Vue's default ones to single ones:
new Vue({
el: '#app',
delimiters: ['${', '}'],
data: {
message: 'Hello Vue.js!'
}
Template:
<td>${ message }</td>
But now it's just not rendered, what I see in a browser is:
${ message }
How to solve this conflict? Am I doing something wrong?
Thanks!
UPD I figured it out. I did several things wrong:
1) I put the script at the "head" section instead of the very end.
2) I didn't add id="app" attribute to some parent element to specify the app object.
After I changed the code everything started working.
Another way to combine Tornado with another template system that uses double-braces is to escape the ones that are to be handled by javascript with {{!:
<h1>This variable comes from Tornado: {{ x }}</h1>
<p>This one comes from Vue: {{! y }}</p>
Tornado's rendering will remove the exclamation point and leave the double braces for Vue to use.
I encountered that as well. This is what worked for me.
Put this in your main.js. N.B you can specify the delimiters to suit your needs
Vue.mixin({ delimiters: ['[[',']]'] })
The in your html you can use it as it is. e.g
<td>[[ message ]]</td>
I am trying to upload a file in my form using the bootstrap-vue form file component
template
<b-form-group id="userInputGroup8" label="User Picture:">
<b-form-file id="userPictureInput" ref="fileinput" #input="userPictureSelected" v-model="userPictureFile" choose-label="Select" accept=".jpg, .png"></b-form-file>
<br> Selected file : {{ userPictureFile.name }}
</b-form-group>
Once the file is selected , the name is displayed in the browser, but it does not appear in the input field, and even if the userPictureSelected method is fired, I don't get its value in the console
script
data () {
return {
...
userPictureFile: '',
}
},
methods: _.extend({}, mapActions(['createUser']), {
userPictureSelected: () => {
console.log('Selected: ', this.userPictureFile.name)
}
}
I get the error
[Vue warn]: Error in event handler for "input": "TypeError: _this2.userPictureFile is undefined"
What could be wrong ? where can I get a good and recent example for uploading such file into my server backend static files directory ?
thanks for update
seems to be an issue not yet solved with bootstrap-vue
Custom input file after choice file nothing change.
I'm using vue#2.1.3 and the vue official webpack template to build an app.
When developing locally, I often see the warning Uncaught TypeError: Cannot read property ... of undefined, but the HTML can be rendered successfully. However, the HTML can't be rendered when it's deployed to Netlify with npm run build command. So I have to treat this warning seriously.
I learned from here that it's because "the data is not complete when the component is rendered, but e.g. loaded from an API." and the solution is to "use v-if to render that part of the template only once the data has been loaded."
There are two questions:
I tried wrap v-if around multiple statements that's generating the warning but personal I think this solution is verbose. Is there a neat approach?
"warnings" in local development turn into "fatal errors"(HTML can't be rendered) in production. How to make them the same? e.g. both of them issue warnings or errors?
Just use v-if on a common parent to all the elements in your template relying on that AJAX call, not around each one.
So instead of something like:
<div>
<h1 v-if="foo.title">{{ foo.title }}</h1>
<p v-if="foo.description">{{ foo.description }}</p>
</div>
Do
<div>
<template v-if="foo">
<h1>{{ foo.title }}</h1>
<p>{{ foo.description }}</p>
</template>
</div>
have you tried to initialize all the data you need? e.g. if you need a b c, you can do:
new Vue({
data: {
a: 1,
b: '',
c: {}
},
created(){
// send a request to get result, and assign the value to a, b, c here
}
})
In this way you wont get any xx is undefined error
Guys are right but I can add something.
If there is possibility that your root element in the condition can be undefined for some reason, it is good practice to use something like that: v-if='rootElement && rootElement.prop'. It will secure you from getting cannot get property prop of undefined as when rootelement is undefined, it will not go further in checking.
2021 vue3
we can use like this
props: {
form: {
type: String,
required: true,
},
setup(props, context) {
console.log(props.form)