Vuejs - Render raw html links to <router-link> - javascript

I;m new to VueJS and I'm making some weird experiments. I build a backend service using python/flask and this backend provide me a string of html code with many tags inside, I want to render this inside my Vue app, I have a method for calling the backend that looks like this:
async execute (method, resource, data) {
return client({
method,
url: resource,
data: data
}).then(async req => {
return req.data.html
})
},
callBack (id) {
console.log(id)
return this.execute('post', '/content/', {body: { 'id': id }})
}
And in the .vue file I have:
export default {
data () {
return {
loading: false,
launch: [],
html: 'none',
page: this.$route.params.article
}
},
beforeMount () {
console.log('beforeee')
this.html = api.callBack(this.page)
},
methods: {
async launch () {
this.launch = ''
this.html = await api.callBack(this.page)
}
}
}
so when I call the launch function it populates this.html, and this html variable lives in a v-html.Everything seems to work i get the html and render it in de container but the links are broken, the links should point at the same app something like #/test/linkvalue, but as they are tags, and in vue you have to use they doesn't work.
There is a way to achieve this "dynamic re route" or I'm doing something too weird?
The links are plenty, since they are scraped from the web, so manually parsing is not an option.
JSFiddle
Thanks in advance for your help

Also, you shouldn't return the raw html. Just return the paths for the routes and then loop the paths and create links that way.
You can use the v-html vue directive to output raw html.
https://jsfiddle.net/eywraw8t/66262/
new Vue({
el: "#app",
data: {
rawhtml: "<h1 style='color: red;'>Hi, I am raw html.</h1>"
},
methods: {
}
})
<div id="app">
<div v-html="rawhtml"></div>
</div>

Related

VueJS / v-html shows empty page (Bokeh-html)

I am new to VueJS and I am trying to display a local html-file inside of the Vue Application.
I fetch the html file with axios like following:
<template>
<div>
<h1>bla</h1>
<div v-html="input"></div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
input: null,
}
},
created() {
this.loadFile()
},
methods: {
loadFile() {
axios({
method: "get",
url: "../../test.html"
})
.then(result => {
this.input = result.data;
console.log("Data: " + result.data)
})
.catch(error => {
console.error("error getting file: " + error);
});
},
}
}
</script>
We generate the html-Files with Bokeh (interactive Charts). If I open the html Files in the Browser they are shown correctly. These files contain
<script type="text/javascript">
and <script type="application/json">.
I tried this with a simple "Hello World"-html Example and this works fine and gets displayed in Vue. But when I read the actual file, I just get an empty page. The console.log(result.data) shows me the correct and complete html Code but I don't get any errors, so I can't figure out the problem.
Does anyone know, what I have to adjust to make this work?
Thanks !
The reason is the statement this.input = result.data tries to parse result.data as json but it is not.
Send the json from the server and use it in your code properly.
Are you doing this inside of a .vue file or is all of this in a .html file. If in html you need to remember to set the el property on your Vue model to ensure it knows where to render. If this is a .vue there has to be a defined template for the same reason.
Here is a fiddle with an example. Yes the site has issues rendering with correct layout, but it renders. This is an example for <script> tags in your html file or just a raw .js file. Looks like you were making a Vue component (.vue) but the premise is still the same as long as you define the template where the Vue code is to be rendered.
Edit:
What does your vue file look like? This is what I'm expecting.
<template id="foo">
<div v-html="input"></div>
</template>
<script>
export default {
template:'#foo',
data: {
input: null
},
created() {
this.loadFile();
},
methods: {
loadFile() {
let _this = this;
axios({
method: "get",
url: 'https://jsfiddle.net/',
})
.then(result => {
console.log(result);
_this.input = result.data;
console.log("Data: " + result.data)
})
.catch(error => {
console.error("error getting file: " + error);
});
},
}
};
</script>

How to write Vue js code in separate file and include in laravel

How to write Vue js code in separate file and include in laravel
Blade page code?
Am also using gulp file.
#section('js')
<script>
new Vue({
// Defining a element.
el: '#branddashboard-html',
data: {
// Defining data variable.
brandStats: null
},
// On load functionality.
created: function () {
// Initializing method.
this.getData();
},
},
// Methods to implement.
methods: {
getData: function () {
self.brandStats = null;
$.get('brand-stats/' + userId + '/' + period, function (data) {
self.brandStats = data;
});
}
}
});
</script>
#endsection
I think this is no the best idea. I think, the Blade's Templates only works in the views folder. Your frontend logic is now managed with Vue Component System, in this MVVM vue way. Hope this be usefull to you

Vue js load modal content with ajax

I'm using vue js with laravel, In my page i have 13 modals, I thing it's not a good idea to insert 13 modals in the same page so i put this in my blade :
<modal v-if="showModal" #close="showModal = false">
<header slot="header" v-html="modalHeader"></header>
<component slot="body" :is="currentBody"></component>
</modal>
And in my file.js i have this :
Vue.component('modal', require('./components/Modal.vue'));
Vue.component('StatusModal', require('./components/modals/StatusModal.vue'));
Vue.component('UserModal', require('./components/modals/UserModal.vue'));
const profile = new Vue({
el: '#profile',
data: {
showModal: false,
modalHeader: '',
currentBody: '',
},
methods: {
showStatus(){
this.showModal = true
this.modalHeader = 'Confirmation'
this.currentBody = 'StatusModal'
},
showUser(){
this.showModal = true
this.modalHeader = 'Confirmation'
this.currentBody = 'UserModal'
}
}
})
Just for example here i have two modals 'StatusModal' and 'UserModal' and i load them in my js file, so if i have 13 or more modals i will load 13 components in my js file, i need a solution that load only component that i need when i call function, It's possible to load component in function call?
I tried to use ajax and load blade content in ajax call and load it in my modal but i face a problem, i'm using vue validation for inputs so validation don't work (vee-validate) also any vue variable does not compiled and i get {{ variable }} in my modal.
What is the best solution for my case? i appreciate any help
Edit after chat
Solution found:
HTML:
<component slot="body" :is="currentBody"></component>
JS:
showStatus() {
this.dialog = true
System.import('./components/modals/StatusModal.vue').then((response) => {
this.currentBody = response
});
},
Previous answer
If using vue-cli webpack config(modules), I'd go for a solution as follow. The key point is using System.import. It's the same thing as require but asynchronous. It will only resolve one time even if you call the same file multiple times. It'll cache it client side.
I use a render function here, because it's a lot easier to manage vue template replacement.
import Modal from './components/Modal.vue'
const profile = new Vue({
render(h) {
if (this.showModal) {
return h('modal', {
on: {
close() {
this.showModal = false
}
}
}, [
h('header', { slot: 'header' }, this.modalHeader),
h(this.currentBody, { slot: 'body' })
]);
} else {
return null;
}
},
data: {
showModal: false,
modalHeader: '',
currentBody: {},
},
methods: {
showStatus() {
this.showModal = true
this.modalHeader = 'Confirmation'
this.currentBody = System.import('./components/modals/StatusModal.vue')
},
showUser() {
this.showModal = true
this.modalHeader = 'Confirmation'
this.currentBody = System.import('./components/modals/UserModal.vue')
}
},
components: {
Modal
}
})
Note I haven't tested it. Let me know if anything goes wrong or if I misunderstood your case.

Get data attributes from v-link

Sure it's a easy thing but at the moment i just can't get it to work. I have a component called posts.vue which includes this link in the template:
<template>
<a v-link="{ name: 'post', params: { slug: post.post_name }}" v-postid="{ post.ID }"><h2>{{ post.post_title }}</h2></a>
</template>
My Routes are set up like this:
'/post/:slug': {
name: 'post',
component: require('./components/post.vue')
}
Now my question is how can i get the postid data attribut in my post.vue component which gets loaded after the route matches.
In my old jquery days i would do it like that:
$('a.link').click(function() {
var attr = $(this).data('post-id');
}
(Just to showcase what i meant)
Thanks for any help guys! Vue.js is great so far, enjoy it alot.
Assuming you have a post object inside your component that you set with ajax after the route is loaded
data: function() {
return {
post: {}
}
}
and
route: function() {
data: function() {
var resource = fetchPost(this.$route.params.slug)
this.$set('post', resource)
}
}
You can access the post.id everywhere in your component like this this.$data.post.id
The v-postid directive is not required for that.

Vue.js - Global Data from AJAX Call

I'm giving Vue.js a try and so far I'm loving it because it's much simpler than angular. I'm currently using vue-router and vue-resource in my single page app, which connects to an API on the back end. I think I've got things mostly working with a the primary app.js, which loads vue-router and vue-resource, and several separate components for each route.
Here's my question: How do I use props to pass global data to the child components when the data is fetched using an asynchronous AJAX call? For example, the list of users can be used in just about any child component, so I would like the primary app.js to fetch the list of users and then allow each child component to have access to that list of users. The reason I would like to have the app.js fetch the list of users is so I only have to make one AJAX call for the entire app. Is there something else I should be considering?
When I use the props in the child components right now, I only get the empty array that the users variable was initialized as, not the data that gets fetched after the AJAX call. Here is some sample code:
Simplified App.js
var Vue = require('vue');
var VueRouter = require('vue-router')
Vue.use(VueRouter);
var router = new VueRouter({
// Options
});
router.map({
'*': {
component: {
template: '<p>Not found!</p>'
}
},
'/' : require('./components/dashboard.js'),
});
Vue.use(require('vue-resource'));
var App = Vue.extend({
ready: function() {
this.fetchUsers();
},
data: function() {
return {
users: [],
};
},
methods: {
fetchUsers: function() {
this.$http.get('/api/v1/users/list', function(data, status, response) {
this.users = data;
}).error(function (data, status, request) {
// handle error
});
}
}
});
router.start(App, '#app')
Simplified app.html
<div id="app" v-cloak>
<router-view users = "{{ users }}">
</router-view>
</div>
Simplified dashboard.js
module.exports = {
component: {
ready: function() {
console.log(this.users);
},
props: ['users'],
},
};
When dashboard.js gets run, it prints an empty array to the console because that's what app.js initializes the users variable as. How can I allow dashboard.js to have access to the users variable from app.js? Thanks in advance for your help!
p.s. I don't want to use the inherit: true option because I don't want ALL the app.js variables to be made available in the child components.
I believe this is actually working and you are being misled by the asynchronous behavior of $http. Because your $http call does not complete immediately, your console.log is executing before the $http call is complete.
Try putting a watch on the component against users and put a console.log in that handler.
Like this:
module.exports = {
component: {
ready: function() {
console.log(this.users);
},
props: ['users'],
watch: {
users: {
handler: function (newValue, oldValue) {
console.log("users is now", this.users);
},
deep: true
}
}
}
};
In the new version of Vue 1.0.0+ you can simply do the following, users inside your component is automatically updated:
<div id="app" v-cloak>
<router-view :users="users"></router-view>
</div>

Categories

Resources