Twig include with rerender - twig

I want to include some template and append on button click (by js), and I need each included template to have a unique id.
Here is the logic where I appending the templates:
<button type="submit" id="addTranslationFields">Add translations</button>
// and js
$('#addTranslationFields').on('click', function (event) {
event.preventDefault();
event.stopPropagation();
let part = `{% include 'translationPart.twig' with {'languages': languages,}%}`;
$('.table tbody').append(part);
});
Here is the how I generate uuid in the translationPart.twig
{% set uuid = uuid() %}
{{ uuid }}
The issue is that UUID is the same for all of the created templates. I understand why it's happening, it's b-z twig generated server-side and at the moment of generation it sees only one include. But is there some option to rerender included template for each new included copy? Or maybe some other way to set different UUIDs for each of the included templates.
Updated
uuid() is a custom twig function
$twig->addFunction(
new TwigFunction(
'uuid',
static function(): string {
return Uuid::uuid4()->toString();
}
)
);

You can achieve this via ajax calls, or string replacement.
String replacement
Twig template (translationPart.twig)
{% set uuid = '#_SOME_STRING_TO_REPLACE_#' %}
{{ uuid }}
Javascript
<button type="submit" id="addTranslationFields">Add translations</button>
// and js
$('#addTranslationFields').on('click', function (event) {
event.preventDefault();
event.stopPropagation();
let generatedUuid = generateUuidByJavascript();
let part = `{% include 'translationPart.twig' with {'languages': languages,}%}`.replace('#_SOME_STRING_TO_REPLACE_#', generatedUuid);
$('.table tbody').append(part);
});
Uuidjs can be used for generating uuid.

Related

How to accès HTML data-attribute with Twig?

Not sure if this is possible, but I've a link with data-attributes 'data-form-recipient' set by Json objects :
<a class="callback-form" href="#location-form" id="contact-us-recipient" data-form-recipient="${myCustomLayers.properties.locationRecipient}">
When trying to get the data from this with JS, It looks all good and gives me the email addresses I want ->
var elem = document.getElementById('contact-us-recipient');
var recipient= elem.getAttribute('data-form-recipient');
console.log(recipient)
Thing is, I need to access it with Twig because this is for a Freeform dynamicNotification (Craft 3), in this context :
{% set form = craft.freeform.form("contactLocation", {
dynamicNotification: { recipients: [
recipient
], template: "locationContactTmp" }
}) %}
Where 'recipient' must be my data-form-recipient value. Is this possible and how?
Thanks

Cascading Template Use in mustache-express?

My intent is to define a page_layout template and a form template as well. Within the route handler i was going to parse the inner (form) template and inject into the greater layout than return.
After several plot twists i'm able to use the response.app to get access to my mustache template engine and parse a view, but the HTML is getting escaped :(
let router = require('express').Router();
let mustache = require('mustache');
router.get('/plant', function(request,response) {
response.app.render('plantForm', {pageTitle: "Plant"},function (err, html) {
response.render ('layout', { pageContent : html});
});
});
yields the outer template with escaped html where I expect content:
<div class="form-group">
<label for="plantNameInput">Plant Type</label>
Perhaps I'm misusing the technology?
From the Mustache documentation:
All variables are HTML escaped by default. If you want to return unescaped HTML, use the triple mustache: {{{name}}}.

Symfony 4 How to add an attribute to a twig using jquery?

I'm trying to do a form with symfony 4. It works fine. But I have a problem.
I have a field to write a comment. By default, it's not required.
However, I would like to change this using jquery.
This is what I tried to do.
Here, it's my twig:
<div class="information" id="informationForm">
{{ form_row(recordForm.category) }}
{{ form_row(recordForm.information) }}
{{ form_label(recordForm.comment) }}
{{ form_widget(recordForm.comment, {'attr': {'class': 'comment'}}) }}
{{ form_errors(recordForm.comment) }}
<button id="add_information_button" class="btn btn-primary">Ajouter un renseignement</button>
<button id="count_div" class="btn btn-primary">Compter</button>
<button class="remove_information_button btn btn-primary">Supprimer un renseignement</button>
</div>
Here it's the javascript:
$('.information')
.on("change", ".record_to_information_form_information", function (event) {
event.preventDefault();
var $commentState = $(this).find('option:selected').data('comment')
//Test: to know if i received the attribute
console.log($commentState)
if($commentState===false){
//the field isn't required
// {{ form_widget(recordForm.comment, {'attr': {'required': 'false'}}) }}
}else{
//the field is required
// {{ form_widget(recordForm.comment, {'attr': {'required': 'true'}}) }}
}
})
;
Do you have any suggestions?
You can toggle required property value from your jQuery code.
I assume that data-comment attribute has type boolean and it's always set, so your toggle statement can look as follows:
$('.information')
.on("change", ".record_to_information_form_information", function (event) {
event.preventDefault();
var $commentState = $(this).find('option:selected').data('comment');
//Test: to know if i received the attribute
console.log($commentState);
$('.comment').prop('required', $commentState);
});
If you need to do something else in your if-else statement, you can just leave your condition as you provided in sample:
if ($commentState === false) {
//the field isn't required
$('.comment').prop('required', false);
} else {
//the field is required
$('.comment').prop('required', true);
}

ejs 2 custom delimiter

EJS2 can only do character to be use with angle brackets for open/close:
ejs.delimiter = '$';
ejs.render('<$= users.join(" | "); $>', {users: users});
I would like to use {{ }} instead of <% %>, previous version will allow this esj.open = '{{' and esj.close = '}}'.
Any help?
EJS has been updated & changed maintainers, so the main site is found here: https://ejs.co/
and the Github is here: https://github.com/mde/ejs
Unlike previous versions of EJS, you can't use completely custom delimiters now - you can use 'partial' custom delimiters - the first set of brackets aren't optional, but the following character is. To set up a custom delimiter you can do the following:
// app.js
const ejs = require('ejs');
ejs.delimiter = '?';
app.get('/', (req, res) => {
res.render('index', {
myVariable: 'Hey!'
});
});
// index.ejs
<div>
<p>
<?=myVariable ?>
</p>
</div>
// index.html (rendered output)
<div>
<p>
Hey!
</p>
</div>
You can add a complete options object and other things, but hopefully that gets you started if you want to change the default delimiters.
Documentation states that custom delimiters are supported:
https://github.com/tj/ejs#custom-delimiters
This isn't possible without modifying the module's source code.
My solution to using custom delimiters is be doing a string replace on the template
const template = fs.readFileSync(path.join(__dirname, './template.html'), 'utf8').replace('{{', '<%').replace('}}', '%>')
const render = ejs.compile(template)
This allows me to declare my template like this:
{{ if (someVar) { }}
{{= someVar }}
{{ } }}

Nodejs use method in view

For example,In my Nodejs app,I have a router:
exports.test=function(req,res){
res.render('./admin/test.jade',{html:[a,b,c]);
}
And I have Underscore.js
In my view test.jade:
-var _und=require('Underscore.js')
....
div
-_und.each(html,function(m))
span m
....
But I got error.This shows that,the Underscore.js is just be used as a server-side method,how can I use a server-side method in view?
You don't need to require underscore from a view. To view you should send just data (it means that in idea case you should not use underscore there at all). But if you would like, you can still send underscore like a function to view:
exports.test = function(req,res) {
res.render('./admin/test.jade',{ html: [a,b,c], _ : require("underscore") });
};
or like this:
exports.test = function(req,res) {
var underscore = require("underscore");
res.render('./admin/test.jade', { html : [a,b,c], _ : underscore });
}
After in your view you can access to that like this:
div
-_und.each(html,function(m))
span m
You can get inspired from my nodejs github markdown project (http://bit.ly/1aOAG35). There is used underscore for layouting and I'm using it as well in templates:
{{# onlyblogs.forEach(function(current){ }}
<li>
{{ current.title }}
{{# if (current.description){ }}
<span>{{ current.description }}</span>
{{# } }}
<span>{{ current.category }}</span> in <date>{{ current.date }}</date>.
</li>
{{# }); }}
Hope that it helped.

Resources