How to use components in v-html - javascript

I am trying to use components in v-html.
I want to get html from own API, then I will show that.
Here is my code.
HTML:
<!-- app -->
<div id="app">
<span v-html="html"></span>
<badge></badge>
<span v-html="html2"></span>
<partial name="my-partial"></partial>
<span v-html="html3"></span>
</div>
Javascript:
Vue.component('badge', {
template: '<span class="component-tag">This is component</span>',
})
Vue.partial('my-partial', '<p>This is a partial!</p>')
// start app
new Vue({
el: '#app',
data: {
html: '<p>THIS IS HTML</p>',
html2: '<badge></badge>',
html3: '<partial name="my-partial"></partial>'
}
})
https://jsfiddle.net/9w3kz6xm/4/
I tried partials because Vue document says " If you need to reuse template pieces, you should use partials."
It does not work. Maybe I am making mistake, I don't know what is a mistake.
Thank you.

Pretty sure Vuejs makes it very hard to directly use external html. v-html will simply replace the html content and therefore will not execute any directive. The purpose of it is to avoid XSS attacks as documented here: https://v2.vuejs.org/v2/guide/syntax.html#Raw-HTML
Dynamically rendering arbitrary HTML on your website can be very dangerous because it can easily lead to XSS vulnerabilities. Only use HTML interpolation on trusted content and never on user-provided content.
If you really need to use external html, it is possible to use Vue.compile() documented here: https://v2.vuejs.org/v2/api/#Vue-compile
A working example can be found here: https://jsfiddle.net/Linusborg/1zdzu7k1/
and its related discussion can be found here: https://forum.vuejs.org/t/vue-compile-what-is-staticrenderfns-render-vs-staticrenderfns/3950/7

Related

Vuejs and drupal

I'm working on a Drupal project where we compile the js and sass of the theme with webpack. As we are moving in a near future to other backend(Laravel), and the idea is to use vuejs on front-end. So it seems to us a good idea, in meanwhile, start using vuejs in some pages and components, so we could start learn it about it. I have experience with angular and react but none with vue. I add it vue, the vue-loader, etc, but seems dificult to make it work and I'm not sure which could be the best way to implement/add vuejs in this escenario. Any recomendation or link will we very helpful.
Introduction
Vue is good choice because of two reasons in your case:
It is simplest to learn than Angular and React
It is progressive - it means you can easy use it only in constrained part of your existing project.
If you look at dock of life cycle of Vue instance
https://v2.vuejs.org/v2/guide/instance.html
You will see there are some options of create template and connect it with instance of vue.
a) by "el" option - selecting existing element from dom
b) by template option
including template as a string
selecting template by id of script with type text/x-template
You can use Vue instantly after page load or mount it later so you have flexibility.
Examples
I understood your question is about simplest way to integrate vue with drupal. I think that these examples of use Vue on simple html page will help you.
Simplest way
Simplest way is use el option and load Vue from cdn. ( remember about change cdn to minified on production )
<style>
[v-cloak] {
display: none;
}
</style>
<div id="app" v-cloak>
<h1>{{ heading }}</h1>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<script>
new Vue({
el: "#app",
data: { heading: "Hello World" }
});
</script>
By using text/x-template
<div id="app"></div>
<script id="app-template" type="text/x-template">
<div>
<h1>{{heading}}</h1>
</div>
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<script>
let v = new Vue({
template: `#app-template`,
data: { heading: "Hello World" }
});
v.$mount();
document.querySelector("#app").appendChild(v.$el);
</script>

Vue.js 2.0: Apply vue component rendered using v-html, compile the markup

I'm using VueJS 2.0
Is there any way to make the below render as a link?
Here is my vue component:
<template>
<div v-html="markup"></div>
</template>
<script>
new Vue({
data() {
return {
markup: '<router-link :to="{path: 'https://www.google.com'}"></router-link>',
});
},
});
</script>
In the above example, I want to dynamically export a piece of markup, it contains some dynamic contents, such as router-link like above.
But that content did not compile, and exports a <router-link> tag as a final result.
Any way to make it compile programmatically?
What I really want is to find a way to compile a piece of html manually. If v-html doesn`t work, Is there any other way?
v-html works only for pre-compiled html which is basically generated text.
If you want do dynamically change content, simply use if conditions to render your list view based on prop that will tell you the type of the list view.
I don't think it's a good idea to save the markup in your db. It's rather more convenient to save some settings in your db and based on those to render the necessary html. (the prop type in your case). Maybe if you provide a more concrete example, some suggestions will follow. As you can see, the answers were based on your router-link example which I think is not enough to answer your question
I don't think you can instantiate Vue instances via v-html directive. You must override the default to do that, which would take lots of efforts.
If you just want dynamic links, why not try this:
data: {
menu: []
}
and then :
<router-link v-for="item in menu" :to="item.src">{{item.name}}</router-link>
PS: Can you give an example that you must do such things? I am really interesting in what needs it would be.
Given that you want to render a list of links, one way to do this can be like this:
<template>
<router-link v-for="list in lists" :to="{path: list}"></router-link>
</template>
<script>
new Vue({
data() {
return {
lists: ['https://www.google.com', 'https://www.stackoverflow.com']
});
},
});
</script>
Edit:
You can use an approach like following as well using with the help of dynamic components.
Vue.use(VueRouter)
new Vue({
el: "#app",
data: {
dynamicComp: "router-link"
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/2.2.0/vue-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<div id="app">
somethind
<component :is="dynamicComp" :to="{path: 'https://www.google.com'}"></component>
</div>

Including HTML file in Javascript

I know this is a solved problem and the question might sound stupid but I come from a mostly backend, mobile and low-level development background.
I am working on a JS application (pure JS, no framework but structured really nicely). The only issue with the application is that all HTML is written in Javascript. So it would look like:
$div = ('<div>Hello</div>');
And then you can imagine how ugly this can get with all the additions and HTML manipulations. Now this HTML eventually ends up getting included into an index.html file that has a standard layout that all other JS files will end up exporting their HTML into somehow (uses some PHP). I want to be able to create a separate HTML file, and have a JS file use that file. How can I do so? I know typically the problem is the other way round: in the HTML, get the JS/template it. But in this app's case, this is not the issue.
With the current app I have, is there a way to use Handlebars or Underscore, or anything similar, to be able to write the HTML in an HTML file and just include it into the Javascript? I understand that this may require some pre-compilation but this isn't a problem.
The examples on Underscore and Handlebars only show simple HTML examples written the way I have it above. Examples online are showing how to template HTML with Javascript, but not precisely what I want.
Anyone has any suggestions or can help please?
I think you can easily do this using JQuery's $.ajax() method. Here's an exmaple:
$.ajax({
type: "GET",
url: "/templates/something.html",
dataType: "xml",
success: function (xml) {
$div = xml;
console.log('Loaded HTML: ', xml);
}
});
Handlebars will work for what you're trying to do, and it's super simple to use!
Let's take a simple example (taken from the handlebars website). Assume this is your HTML:
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
All you have to do is put it in a file (let's call it html.handlebars) then reference that file in a script tag:
<script id="html-template" type="text/x-handlebars-template" src="./html.handlebars"/>
Then from your Javascript you can create a template:
var source = $("#html-template").html();
var template = Handlebars.compile(source);
then generate the HTML from the template:
var context = {title: "My New Post", body: "This is my first post!"}
var html = template(context);
at this point html will be:
<div class="entry">
<h1>My New Post</h1>
<div class="body">
This is my first post!
</div>
</div>
which you can use just like any other string of html (ex: $(html).appendTo('body')).
You can make as many handlebars templates as you want, ranging in size from full pages to small snippets as above.
If performance becomes an issue you can look into precompiling as well: http://handlebarsjs.com/precompilation.html

Are'nt we Allowed to write html codes if we use backbone.js?

I am learning backbone.js and I have seen some examples like this one.Here the user has not written much html codes inside the editor.html.Only 4 lines of code.But for colour change,size change etc he has done inside editor.js
Please help me understand what all codes we need to keep inside .html file
<div id="page" style="width:2000px;height:2000px;">
<button id="new-rectangle">New Rectangle</button>
<button id="new-circle">New Circle</button>
</div>
You should aim to put all your html in .html file(s). As an app grows, it will help you to keep them separate. The example you link to is a 'simplified' version - this is not how you would structure things in an actual app. You would load html from templates in the render function. A (though this is also simplified as I am relying on script tags) pattern would be:
HTML file:
[...SOME HTML...]
<script type="text/html" id="template-contact">
<div class='contact'>
<h1>Here's my template code</h1>
<strong>name</strong>
<span>email</span>
</div>
</script>
Then in your Backbone view render function:
render: function() {
template: _template($('#template-contract').html(),
this.$el.html(this.template());
return this;
}
Then somewhere else in your Backbone code you create a new instance of the view and render it.
var example = new view_name();
example.render(); //This loads the html template
If you need to dynamically load the html from a server, you can use underscore (or whichever template engine you are using) tags in your template '<%>' and use models. This is best explained in Addy Osmani's book Developing Backbone.js Applications which, incredibly, is free. Here's the link to the relevant section
Whatever you wants to display on the browser you can keep it in .html file and logic to update the dom on run time should be in .js file.

Using agility.js for page layout and composition

I am new to MVC-style javascript libraries, so pardon me if this question is too basic. I'm trying to write a Single-Page Application entirely in jQuery and agility.js. The examples given in the agility.js documentation consist entirely of adding html elements to the document root. Question: Is there a 'Best-Practices' way to assemble a page by components.
Here is a rough outline of my html app:
<html>
<head> ... </head>
<body>
<header> ... </header>
<div id=PageHolder>
<div id=AppPane_1></div>
<div id=AppPand_2></div>
</div>
<footer> ... </footer>
</body>
</html>
Within the 'AppPane' divs will be the content of the application.
Okay, given all of this, I'm not asking what can I do, but I'm asking what should I do.
I see from the documentation and my research that I have 3 choices:
create my page composition from atomic agility objects and assemble them in a jQuery document ready block. $$.document.append(Foo) works for the root element, but I could not figure out how to add Foo's children to foo.
Use one (very large) agility object which lays out the basic static html from above and append controls and whatnot to that using the controller functions (which I havn't been able to get to work either)
Use one root agility object and append all the children onto it using view (somehow, I havn't been able to get that to work either.)
Which of these is best, and what is the syntax involved? Thanks in advance, any guidance in assembling html components into a cogent agility app would be much appreciated.
http://jsbin.com/ojenon/1/
In my opinion, the best way to organize your page modules is to save individual client-side templates in script tags in the head:
<html>
<head>
<script type="text/template" id="template1">
<b>Some <abbr>HTML</abbr> template</b>
</script>
<script type="text/template" id="template2">
<b>Some <abbr>HTML</abbr> template</b>
</script>
</head>
...
You could even choose to use a template language, such as jQuery.template or handlebars.js, to facilitate logic, variable interpolation, etc.
Then, in your your controller, you would load the html contents of these templates' script tags from the DOM and copy them into your destination div (#PageHolder) as appropriate.
An alternative to this technique would be storing your templates in a literal JS object in the head:
<script type="text/javascript">
var Templates = {
template1: "<b>Some <abbr>HTML</abbr> template</b>"
...
}
</script>
This is just the beginning. There are many more options, such as pre-compiling your templates, subdividing your templates to avoid redundant template compilations, etc. From a structural standpoint, maintaining your templates in a dedication location will help you scale your single page app.
It's horses for courses I guess, but my preference is to have the template code alongside the Agility code so that it's all visible together. I don't particularly like seeing the html and styling inside the view object, but you can set these up in other variables and reference them in the view like this:
var frmMainTemplate = '<div>' +
'<input type="text" data-bind="name" />' +
'<p>You typed <span data-bind="name" /></p>' +
'</div>';
var frmMainStyle = '& span {background-color:#888; color:#fff;}';
var frmMain = $$({
model: {name:''},
view: {
format: frmMainTemplate,
style: frmMainStyle
},
controller: {}
});
$$.document.append(frmMain);

Categories

Resources