I am building an app using express handlebars for server-side templating. On the client side, I want to use vue.js. However, they both share the same double brace notation {{ variable }}. Right now, my vue.js variables are not showing because my handlebars template is overriding it. For example:
home.html:
<div id="app">
{{message}} //this will not show up
</div>
home.js:
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
});
HOWEVER, if I define message in my server side controller:
res.render('../views/home', {
message: 'message from handlebars'
});
the message will show up.
So in summary, is there a way i can use vue.js for client side templating while still using express-handlebars for server side templating?
Thanks in advance!
This can be solved by escaping the first brace in your handlebars template.
<div id="app">
\{{message}} //this will not be replaced by handlebars
</div>
You can change the Vue demlimiters to something else, e.g.:
Vue.config.delimiters = ['${', '}']
You can "escape" the Vue delimiters in Handlebars by using a raw block helper:
Handlebars.registerHelper('vue-js', function(options) {
return options.fn();
});
Usage in the Handlebars template:
{{{{vue-js}}}}
<div id="app">
{{message}}
</div>
{{{{/vue-js}}}}
Related
got this code from preact's site, and try to make it work without babel building process, but failed, anybody knows if this is possible? Thanks,
http://jsfiddle.net/e281k4wz/117/
'use strict';
const { Component, h, render } = window.preact;
render((
<div id="foo">
<span>Hello, world!</span>
<button onClick={ e => alert("hi!") }>Click Me</button>
</div>
), document.body);
Yes. You have to include babel before your jsx code and use the script as type="text/babel" see the following example with react
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
class App extends React.Component {
render() {
return (
<div className="app-content">
<h1>Hello from React</h1>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'));
</script>
</body>
</html>
You cannot directly use the JSX into the JavaScript as it's a invalid syntax.
For running the preact into the client you have to either transpile the jsx code into valid javascript or use the helper method (Component , h , render) provided by preact.
HTML
<h1>Render by Preact client library using h and render function</h1>
<div id="preact">
</div>
JavaScript
var Component = window.preact.Component,
h = window.preact.h,
render = window.preact.render;
var PreactApp = function (props){
return h('h1',
{className: ''},
'Hello from Preact world!');
}
render(PreactApp(),document.getElementById("preact"));
Here in JS if you see h ( converting jsx to vdom ) and render (converting vdom to html ) function actually do the magic. Read more about from the official documentation - https://preactjs.com/guide/api-reference
Working example - https://jsfiddle.net/97125m3z/2/
Technically it is possible by using the HTM package, as long as you're targeting recent browsers that understand template strings. See https://github.com/developit/htm for details.
However, this will render slower than simply creating the components using h() as it is a whole heap of string parsing. It also makes it difficult to use syntax highlighting in your IDE, which makes debugging frustrating.
I used HTM when I was first getting used to using Preact without a build step, but very quickly replaced it with manually creating the components and eliminated the JSX.
You get a better understanding of how everything fits together if you don't use the JSX abstraction. Babel compiles it down into createElement calls anyway.
I am new to VueJS and I am confused why a simple example from the docs is not working for me.
This is all the code. I am expecting it to display "Howdie Partners" on the page.
HTML
<div id="app">
<greeting></greeting>
</div>
JS
Vue.component('greeting', {
template: '<h1>{{message}}</h1>',
props: ['message']
});
var vm = new Vue({
el: '#app',
data: {
message: "Howdie Partners!"
}
});
JSFiddle Link: https://jsfiddle.net/hq1yu0ct/
From the documentation:
we can also use v-bind for dynamically binding props to data on the parent. Whenever the data is updated in the parent, it will also flow down to the child.
So you need to pass the props in the greeting component like following:
<div id="app">
<greeting :message="message"></greeting>
</div>
check working fiddle here.
I want to render the pure HTML coming from some external source into react component. I saw few solutions where people are talking about some conversion tools (HTML to JSX) but I want to handle everything in my component so while mounting it will get the HTML response and that needs to render.
You can use dangerouslySetInnerHTML for this:
function createMarkup() { return {__html: 'First · Second'}; };
<div dangerouslySetInnerHTML={createMarkup()} />
But as the method name suggests: you should be very sure of what you are doing there and the security implications it has.
This shouldn't be difficult to do . Assign your HTML to a div and then render it using {variable name} JSX allows you to do this and with ES6 integration you can also use class instead of className.
var Hello = React.createClass({
render: function() {
var htmlDiv = <div>How are you</div>
return <div>Hello {this.props.name}
{htmlDiv}
</div>;
}
});
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
I am using iron router to render a template within meteor framwork, as i was following probably an outdated tutorial, it seems to me there is a change in syntaxes which i could not figure out.
layout.html
<div class="container">
<div class="row">
<div class="span2">
<p>cell</p>
</div>
<div class="span7">
<p>cell</p>
</div>
<div class="span3">
<p>cell</p>
</div>
</div>
</div>
index.js
function.setDefault ('category', null );
Router.configure({
layoutTemplate:'layout',
yieldTemplates:{
'products':{to:'products'},
'cart':{to:'cart'},
'categories':{to:'categories'}
}
});
Router.route(function(){
this.route('/', layout);
this.route('/products',{
data:function(){
Session.set('category',this.params.name);
},
template:'layout',
path:'/:name'
})
});
The following error occurs
unexpected token (1:8)
Where you have Router.route and use this.route in a function, Router.route should read Router.map however this is deprecated in favour of Router.route (without the map wrapper) as below:
Session.setDefault ('category', null );
Router.configure({
layoutTemplate:'layout',
yieldTemplates:{
'products':{to:'products'},
'cart':{to:'cart'},
'categories':{to:'categories'}
}
});
//You will need to declare a template at the least here so it knows what to render to main area
Router.route('/', {template: "template_name");
Router.route('/products/:name',{
onBeforeAction:function(){
Session.set('category',this.params.name);
this.next ();
},
//you don't need this to be layout
//as you are defining a default layout above
//but you will need to specify a template for the main yield area
template:'template_name'
// you don't need to specify path here as it will use '/products'
//if you want to specify a route name use line below
//,name: 'routename'
});
Where url would be /products/product_name
Where template_name is the template you want to render in your main {{> yield}}
In your layout template you need to place the following for your yields wherever you want to display them
{{> yield 'products'}}
{{> yield 'categories'}}
{{> yield 'cart'}}
{{> yield }} //this is the template you specify in template: 'template_name'
(Done from my phone so can't test but can update later if it doesn't work for you)
I'm trying to integrate a Braintree payment solution using Javascript & Node JS.
As per the Braintree documentation, I have the following in my html:
<div id="panel-payment">
<div id="payment-form"></div>
<input id="btn-checkout" type="submit" value="Process Order">
</div>
<script>
$(document).ready(function(){
console.log(braintree); <---- defined AOK
console.log(braintree.Environment); <---- undefined
console.log(braintree.Environment.Sandbox); <---- undefined
var clientToken = "...";
braintree.setup(clientToken, "dropin", {
container: $("#payment-form")
});
});
</script>
I can't get the environment variable, yet the braintree object seems to instantiate fine? Anyone have any ideas?
The braintree object returns:
Object {api: Object, cse: Object, paypal: Object, dropin: Object, Form: Object…}
I also get the dreaded "Unable to find valid container" when I call the braintree.setup() function, even though the container value $("#payment-form") is valid value and I am calling the setup function when the HTML has loaded..
The Environment variable is only available in the NodeJS package.
See here.
For the client side in javascript your need a valid token generated by your server.
So you need a dedicated route delivering a token with the Braintree node package as described here.
And for your container problem try to pass only the id of the div to braintree, not a jQuery element.
braintree.setup(clientToken, "dropin", {
container: "payment-form"
});
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
#chambo_e's answer is correct regarding the difference between the attributes accessible on the node package versus Braintree.js. The environment attribute is only available on the Braintree node module.
I am guessing that the error you are actually seeing is "Uncaught Unable to find a valid FORM" and that is because your payment forms are not enclosed by a form element. By default, Braintree.js looks for the nearest parent form.
<form id="checkout" method="post" action="/checkout">
<div id="panel-payment">
<div id="payment-form"></div>
<input id="btn-checkout" type="submit" value="Process Order">
</div>
</form>
<script src="https://js.braintreegateway.com/v2/braintree.js"></script>
<script>
$(document).ready(function(){
var clientToken = "client token generated form server";
braintree.setup(clientToken, "dropin", {
container: $("#payment-form")
});
});
</script>
If you'd like it to use a different form, you can specify that in the setup call. See these docs for more details
<div id="dropin-container"></div>
<form id="checkout-form">
<input type='submit' value='Pay'/>
</form>
<script>
braintree.setup("CLIENT-TOKEN-FROM-SERVER", "dropin", {
container: "dropin-container",
form: "checkout-form"
});
</script>