Still cannot assign a variable from flask to vue.js - vue.js

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

Related

Currently working with Vue. Project in development phase so I used https://unpkg.com/vue. Although the desired text is not displaying

H1 not displaying "Welcome to Vue" it sill displays {{tile}}
<div id="myApp">
<h1>{{title}}</h1>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
new Vue({
el : '#myApp' ,
data : {
title : 'Welcome to Vue'
},
});
Please try the below code in addition to what Dan mentioned in his answer
new Vue({
template: `<h1>{{ title }}</h1>`,
data() {
return {
title : 'Welcome to Vue'
};
}
}).$mount("#myApp");
That Unpkg link is for Vue 3 but your code is Vue 2 code. If you don't specify a version number with Unpkg, it will give you the latest version.
The official Vue docs presented that unversioned Unpkg link for years before only very recently fixing it. Maybe that's where you found it. Anyone using that link had any existing apps broken when Vue 3 released. (I had hundreds of demos using it!)
I'd suggest using Cloudflare:
Vue 2:
https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.7/vue.min.js
Vue 3:
https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.37/vue.global.prod.min.js

Vue.js - Embed Swagger UI inside a Vue component?

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!

Conflict on template of Tornado and Vue

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>

vue: Uncaught TypeError: Cannot read property ... of undefined

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)

Multi language support in Hot towel(Durandal framework)

I'm in the process of creating a application using Hot Towel, which supports multiple language (eg. english, french)
I have the referred the following links
Translating Views
Durandal localization example
And my question is how can i render views of application based on user language. If user selects english, the complete application should display contents in english. How to achieve this
I have tried something like in the second link.
define({
'root': {
welcome: 'Welcome!',
flickr: 'Flickr'
},
'fr-fr': true,
'es-es': true,
});
Is this i have to create seperate views for languages or i have to create seperate App folder for contents
Suggest me some best practices.
I don't recommend using separate views or separate folders if your project is a big one.
You can just create a file of the labels and if you use lib like knockout just data-bind these labels once (text: xxxx). In addition you can use i18n to manage labels.
With selected language just load the specific language file to your viewmodel.
EDIT1:
I'd never encountered a complete sample nor tutorial. So how I do is to :
use tools like i18n to get the key-paired dictionary file for labels in html and in some javascript code like messages.
then manually I indexed these labels by augmenting knockout viewmodels for views and variables for modules.
This is my last option in waiting for better solution. Hope this can help!
you can do some thing like this . YOu can change the APP folder if you are need do lot of locale changes you can use the following method
#{
string strAcceptLanguage;
strAcceptLanguage = System.Configuration.ConfigurationManager.AppSettings["Locale"].ToString();
if (strAcceptLanguage == "en-us")
{
#Scripts.Render("~/Scripts/vendor.js")
<script type="text/javascript" src="~/Scripts/require.js" data-main="en-US/main"></script>
}
else if (strAcceptLanguage == "es-es")
{
#Scripts.Render("~/Scripts/vendor.js")
<script type="text/javascript" src="~/Scripts/require.js" data-main="en-UK/main"></script>
}
else if (strAcceptLanguage == "fr-fr")
{
#Scripts.Render("~/Scripts/vendor.js")
<script type="text/javascript" src="~/Scripts/require.js" data-main="AUZ/main"></script>
}
}
in the Index.cshtml you can use the above code and for the you need to have value in Webconfig file
<add key="Locale" value="en-us" />
and in the SPA page each time when the user try to change the locale by pressing button or any kind of option you have to trigger a event to call a AJAX post to assess a REST api to update the Given Locale Value in the webconfig file
changeLocale: function (val) {
var name = JSON.stringify({
locale: val
});
$.ajax({
cache: false,
url: "http://localhost:49589/api/Locale",
type: "POST",
dataType: "json",
data: name,
contentType: "application/json; charset=utf-8",
processData: false,
success: function (json) {
alert(json);
location.reload();
},
error: function (json) {
alert("error" + JSON.stringify(json));
}
});
you have to write the above code in the shell.js and the shell.html has the following code
<div class="btn-group" data-toggle="buttons-radio">
<button type="button" class="btn btn-primary" data-bind="click: changeLocale.bind($data, 'en-us')">English</button>
<button type="button" class="btn btn-primary" data-bind="click: changeLocale.bind($data, 'es-es')">French</button>
<button type="button" class="btn btn-primary" data-bind="click: changeLocale.bind($data, 'fr-fr')">Japanese</button>
</div>
And the rest api like this
[HttpPost]
public string ChangeLocale(Locale l)
{
ConfigurationManager.AppSettings["Locale"] = l.locale;
return "success";
}
hope this will help