I'm using Symfony 5 / twig with webpack.encore and vue.js.
I passing datas (translation texts) to the used twig-template like this:
Controller:
class HomepageController extends AbstractController
{
const PAGE_ID = 2; // constants PageId
/**
* #Route("{_locale}/homepage", name="app_homepage")
*
*/
public function index(Request $request,SpracheRepository $spracheRepository)
{
$arrTrans = $spracheRepository->findAllOfSpecificPage(self::PAGE_ID,$request->getLocale());
return $this->render('core/homepage/homepage.html.twig', [
'headline' => $arrTrans['lb_overview'],
'pageId' => self::PAGE_ID,
'arrTrans' => $arrTrans
]);
}
}
...and I'd like to access the datas "arrTrans" in the vue file.
The html.twig is looking like:
{% block content %}
<div id="app"></div>
{% endblock %}
{% block stylesheets %}
{{ parent() }}
{{ encore_entry_link_tags('homepage') }}
{% endblock %}
{% block javascripts %}
{{ parent() }}
{{ encore_entry_script_tags('homepage') }}
{% endblock %}
The corsponding .js file:
import Vue from 'vue';
import App from '../vue/homepage'
new Vue({
render: (h) => h(App),
}).$mount('#app');
...and the vue file themselfe: (I'd like to use the arrTrans in the div of the "button-overview-lable")
<template>
<div class="button-overview">
<div class="button-overview-lable">{{ arrTrans['lb_planning'] }}</div>
</a>
</div>
</template>
<script>
export default {
name: "Homepage",
}
</script>
<style lang="scss">
#import "../../../core/app/css/helper/variables";
#import "../css/homepage";
</style>
If you need to pass data from your template file to a javascript file you can use data attribute.
<div id="app" data-trans="{{ arrTrans | json_encode() }}"></div>
new Vue({
el: '#app',
data: {
trans: null
},
mounted: function() {
this.trans = this.$el.getAttribute('data-trans');
}
});
You can create a JS variable in twig template and pass json-encoded array. Like this (also we disable automatic html-escaping using raw filter):
{% block content %}
<script>
const arrTrans = JSON.parse('{{ arrTrans|json_encode()|raw }}')
</script>
<div id="app"></div>
{% endblock %}
But you have to deal with ' character in your locale strings because it will cause JS syntax error. Replace raw filter with escape('js').
So, the final twig template is:
{% block content %}
<script>
const arrTrans = JSON.parse('{{ arrTrans|json_encode()|escape('js') }}')
</script>
<div id="app"></div>
{% endblock %}
Then in vue app you will just use this variable in data:
<template>
<div class="button-overview">
<div class="button-overview-lable">{{ arrTrans.lb_planning }}</div>
</a>
</div>
</template>
<script>
export default {
name: 'Homepage',
data() {
return {
arrTrans,
};
},
};
</script>
<style lang="scss">
#import "../../../core/app/css/helper/variables";
#import "../css/homepage";
</style>
Thanks for the answers, but I had some problems to implement them. What's now working for me was:
Homepage.html.twig
<div ref="translation" data-translation="{{ arrTrans|json_encode() }}"></div>
Homepage.js
new Vue({
el: '#app',
render: (h) => h(App),
})
homepage.vue
<template>
<div>
<div>{{ trans }}</div>
<div>{{ trans['lb_planning'] }}</div>
</div>
</template>
export default {
name: 'HomePage',
data() {
return {
trans: {}
};
},
mounted() {
let elTrans = document.querySelector("div[data-translation]");
let myTrans = JSON.parse(elTrans.dataset.translation);
this.trans= myTrans;
}
}
Related
My twig file looks like this:
<select name="lineItems[{{ product.id }}][quantity]"
class="custom-select product-detail-quantity-select">
{% for quantity in range(product.minPurchase, product.calculatedMaxPurchase, product.purchaseSteps) %}
<option value="{{ quantity }}">
{{ quantity }}{% if product.packUnit %} {{ product.packUnit }}{% endif %}
</option>
{% endfor %}
</select>
I want to change this into a Vue.js app with a quantity/count field and an 'increment' and 'decrement' button.
My Vue.js app looks like this:
<div id="app">
<a class="btn" v-on:click="increment">Add 1</a>
<a class="btn" v-on:click="decrement">Remove 1</a>
<span>[[ count ]]</span>
</div>
<script>
const App = new Vue({
el: '#app',
delimiters: ['[[',']]'],
data() {
return {
count: 1
}
},
methods: {
increment() {
this.count++
},
decrement() {
this.count--
}
}
})
</script>
If you look at my twig file, you see for example the twig variable {{ quantity }}.
How do I use this twig variable in my Vue.js app? So when the user increment the <span>[[ count ]]</span> value by 3. It add's 3 to the {{ quantity }} variable?
Shopware is not using twig. It is using twig.js for the block system. E.g. for overwriting certain parts in the templates. The logic have to be implemented in the vue component. Please descibe your full problem for more information.
Im trying to use the OpenLayers library in my symfony application. Im using Webpack encore for managing my assets. I've used npm to download the OpenLayers library.
When im trying to use it inside a js file, only the first 'ol' class is available, the classes underneath it are not. In browser the ol.layer.Tile class is not recognised and throws an exception(Uncaught type error).
// map.js
require('../css/map.css');
const ol = require('ol');
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
//map.html.twig
{% extends '::base.html.twig' %}
{# STYLESHEETS-------------------------------------------------- #}
{% block stylesheets %}
{{ parent() }}
<link href="{{ asset('build/map.css') }}" rel="stylesheet" />
{#<link href="https://openlayers.org/en/v4.6.5/css/ol.css" rel="stylesheet" type="text/css"/>#}
{% endblock %}
{# JAVASCRIPTS-------------------------------------------------- #}
{% block javascript %}
{{ parent() }}
{#<script src="https://openlayers.org/en/v4.6.5/build/ol.js" type="text/javascript"></script>#}
<script src="{{ asset('build/map.js') }}"></script>
{% endblock %}
{# PAGE CONTENT-------------------------------------------------- #}
{% block title %}OpenLayers example{% endblock %}
{% block body %}
<body>
<h2>My Map</h2>
<div id="map" class="map"></div>
</body>
{% endblock %}
No need to add script tag if you are using require
`{#<script src="https://openlayers.org/en/v4.6.5/build/ol.js" type="text/javascript"></script>#}`
You should require also Tile, View
var ol_Map = require('ol/map').default;
var ol_layer_Tile = require('ol/layer/tile').default;
var ol_source_OSM = require('ol/source/osm').default;
var ol_View = require('ol/view').default;
var map = new ol_Map({
target: 'map',
layers: [
new ol_layer_Tile({
source: new ol_source_OSM()
})
],
view: new ol_View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
See the document from OpenLayers http://openlayers.org/en/latest/doc/tutorials/browserify.html
I use Symfony3 with Twig template and VueJs 2.
My symfony controller returns a Twig view with Articles component :
{% extends 'base.html.twig' %}
{% block body %}
<Articles></Articles>
{% endblock %}
And my Articles.vue component :
<template>
<section class="articleapp">
<header>
<h1>Mes articles</h1>
</header>
<div class="main">
<li class="article" v-for="article in articles">
{{ article.title }}
</li>
</ul>
</div>
</section>
</template>
<script>
export default {
data () {
return {
articles: [{title: "Voici le nom d'un article"}]
}
}
}
</script>
I would like translate my title "Mes articles" with Sf/Twig i18n like {{ "Mes articles"|trans({}, "") }} to benefit of translate catalogs.
With Single page component it's impossible.
But with X-Template, the problem can be resolve :
index.html.twig :
{% extends 'base.html.twig' %}
{% block title %}{{ "Mes posts"|trans({}, 'app') }}{% endblock %}
{% block body %}
<div id="app">
<post-form></post-form>
</div>
{% endblock %}
{% block components %}
{{ include("components/form.html.twig", {"form": form }) }}
{% endblock %}
components/form.html.twig :
<script id="post-form-template" type="text/x-template">
<div>
{{ "Mon formulaire"|trans({}, '') }}
{{ form(form) }}
<h1>${ greetings }</h1>
</div>
</script>
And my app.js :
import Vue from "vue";
import VueResource from "vue-resource"
Vue.use(VueResource);
Vue.component('post-form', {
delimiters: ['${', '}'],
template: '#post-form-template',
data: function () {
return {
greetings: 'Hello'
};
}
});
new Vue({
delimiters: ['${', '}'],
el: "#app"
});
I need to output data and fill my template throught custum function
this is my imports
<script src="{{ asset('bundles/.../handlebars/handlebars.js') }}"></script>
<script src="{{ asset('bundles/.../handlebars_helpers.js') }}"></script>
this is my template into twig page
<script id="di_template" type="text/x-handlebars-template">
{% verbatim %}
<h1>Title </h1>
Invoice {{ invoice.invoice_number }}
{% endverbatim %}
</script>
this my build Template Function
function buildTemplate(){
context = {
invoice: {
invoice_number: 'val1',
invoice_date: 'val2',
invoice_due_date: 'val3',
invoice_from_company: 'val4'
}
};
template = $('#di_template').html();
template_compiled = Handlebars.compile(template);
theCompiledHtml = template_compiled(context);
$invoice_preview.html(theCompiledHtml);
}
this my result
I would like to render a reactJS component from twig template. Is it possible?
I tried:
<div class="top-line">
<h1>{{ username }}</h1>
{% verbatim %}
<script type="text/html" id="follow-button">
<FriendshipButton user={{ app.user }} />
</script>
{% endverbatim %}
<div id="follow-button-mp"></div>
</div>
And in JS side:
React.render(
React.createElement(document.getElementById('follow-button').innerHTML),
document.getElementById('follow-button-mp')
);
Getting an error:
Uncaught Error: Invariant Violation: Invalid tag:
<FriendshipButton user={{ app.user }} />
Twig:
<script type="text/javascript">
// you might have to serialise user to JSON here if you
// want a more complete user object
var user = '{{ app.user.id }}';
</script>
Javascript component (using JSX)
React.render(
<FriendshipButton user={user} />,
document.getElementById('follow-button-mp')
);