I'm trying to reuse the same HTML code in both PHP and Javascript. In PHP I'm using Laravel's component mechanism to load the file passing the necessary parameters.
#foreach($files as $file)
<x-my-file name="my_name[][image]" imageId="{{ $file->id }}" imageUrl="{{ $file->url }}" />
#endforeach
It's working just fine.
At the bottom of the page, I'm using jQuery like below:
#push('scripts')
<script>
var imageId = null;
var imageUrl = '';
jQuery(function($) {
$('body').on('click', '#btn-add', function() {
var imageId = $(this).data('id');
var imageUrl = $(this).data('url');
$('#target').append(`#include('components.my-file', ['name' => 'my_name[][image]', 'imageId' => 15, 'imageUrl' => '/path/to/an-image.jpg'])`);
});
});
</script>
#endpush
Everything just works fine. With every click, the same component is getting appended with the same data that I've passed.
But, if I replace the static values of the following line:
$('#target').append(`#include('components.my-file', ['name' => 'my_name[][image]', 'imageId' => 15, 'imageUrl' => '/path/to/an-image.jpg'])`);
with the dynamic values I have, using the Javascript template literals:
$('#target').append(`#include('components.my-file', ['name' => 'my_name[][image]', 'imageId' => ${imageId}, 'imageUrl' => ${imageUrl}])`);
The page stopped rendering with a Parse error from Laravel:
ErrorException
Use of undefined constant imageId - assumed 'imageId' (this will throw an Error in a future version of PHP)
Alternative?
I've seen some AJAX methods on loading blade in Javascript that I personally did not like.
Debugging
If I comment out the line, it still throws the same error until I remove the line completely. Hence I'm suspecting that the curly braces of the JS template literals (${}) are getting parsed as a Laravel blade syntax ({{}}).
Please note that instead of the backticks (`) I tried with the single quote and double quotes (as can be seen here), but getting errors as they are conflicting with the HTML code.
I've gone through the Laravel Documentation on Blade and JS Frameworks, but IMO, both the # syntax and #verbatim are for the exact opposite purpose, and won't serve me.
Update
I eventually came up with an alternative to have blade in JavaScript:
#push('scripts')
<script type="text/template" id="my-template">
#include('components.my-file', ['name' => 'my_name[][image]'])
</script>
<script>
var template = document.getElementById('my-template').innerHTML;
console.log(template); // Successful grabbing the HTML.
$(template).find('.image-placeholder').attr('src', imageUrl); // Replaced the HTML with the modified img tag only.
console.log(template.prop('outerHTML'));
</script>
#endpush
With this code, I can have the HTML perfectly without the dynamic data. The first console.log is showing the HTML perfectly:
<div>
<img src="" alt="" class="image-placeholder">
<input type="hidden" name="my_name[][image]" value="">
</div>
Now, the template is not a Laravel blade/component so far, so I have to put my dynamic data onto it. When I'm trying to put my dynamic data onto the HTML, the HTML is being replaced by the modified <img> string completely. The second console.log output is:
<img src="/dynamic-path/to/the-image.jpg" alt="" class="image-placeholder">
Blade components are served by laravel.
After response returned from server blade component won't work anymore.
You can use some kind of placeholder and replace them dynamically as you did last time.
As example,
var template = document.getElementById('my-template').innerHTML;
template = template
.replace('{src}', 'https://example.com/image.jpg')
.replace('{id}', 'ImageID')
.replace('{name}', 'my_name[][image]')
console.log(template)
<!--
<script type="text/template" id="my-template">
<x-my-file name="{name}" imageId="{id}" imageUrl="{src}" />
</script>
I am using a template below
-->
<script type="text/template" id="my-template">
<div>
<img src="{src}" id="{id}" class="image-placeholder">
<input type="hidden" name="{name}" value="">
</div>
</script>
Related
I'm using the underscore library to populate my template.
It works like a charm when my variable day is inside a tag. like this snippet from my code:
<template>
<label>Schedule</label>
<select class="form-control" onchange="set_from_hour('<%=day%>')" name="some_name" id="<%=day%>from_hour" >
<option value=0 selected='selected'>00</option>
<option value=1>01</option>
...
</template>
to populate this template I use this function:
days_schedule = ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']
function show_schedule_week(){
_.each(days_schedule,function(day){
_.templateSettings.variable = 'day'
var template = _.template($('template').html())
console.log(day+'_schedule')
$('#'+day+'_schedule').prepend(template(day))
})
}
Now the problem comes when i want my HTML code to display the variables, say in a header tag the variable day like below:
<template>
<h1> <%- day%> </h1>
</template>
The browser displays
<%- day%>
instead of the value of the variable.
Do you know what I'm doing wrong?
The problem is with the string that you pass to _.template(): the HTML that you read from the DOM does not have <%- day%>, but <%- day>. This is because < has a special meaning in HTML, and as here it does not represent a tag, it is encoded with an HTML entity. The same goes for >.
There are several solutions to this. One is to not use a template element in your HTML, but a string literal in your code. If however you prefer to stick with the template element (which is reasonable), then you could turn the template content into an HTML comment.
Here is an example:
days_schedule = ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']
function show_schedule_week() {
_.each(days_schedule,function(day){
_.templateSettings.variable = 'day'
// unwrap the template content by removing the HTML comment tag start/end
var template = _.template($('template').html().slice(4, -3));
$('#'+day+'_schedule').prepend(template(day))
})
}
show_schedule_week();
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.11.0/underscore-min.js" integrity="sha512-wBiNJt1JXeA/ra9F8K2jyO4Bnxr0dRPsy7JaMqSlxqTjUGHe1Z+Fm5HMjCWqkIYvp/oCbdJEivZ5pLvAtK0csQ==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.js"></script>
<template><!--
<h3> <%- day%></h3>
--></template>
<div id="monday_schedule"></div>
So I have a flask app that has only one template (html file). The html file is changed through a javascript file. It changes the DOM through jquery and flask doesnt have a problem with this. However, when I'm changing a img tag it has trouble.
This is my javascript code.
$(document).ready(function(){
mainPage = $("#mainPage");
setMainPage();
});
function setMainPage(){
mainPage.html('<div><img src="{{ url_for('static',filename='images/facebook.png') }}" alt="icon" class="socialBtns"></div>');
}
this returns the error: "missing ) after argument list" and the error happens on the line number where I set mainPage.html(). So i thought it was the ' quotes that were causing the problem. so I escaped them using the backslash like this:
$(document).ready(function(){
mainPage = $("#mainPage");
setMainPage();
});
function setMainPage(){
mainPage.html('<div><img src="{{ url_for(\'static\',filename=\'images/facebook.png\') }}" alt="icon" class="socialBtns"></div>');
}
But when i do that all the text loads in just fine but the image spits out an error "http://127.0.0.1:5000/%7B%7B%20url_for('static',filename='images/facebook.png')%20%7D%7D 404 (NOT FOUND)"
So i tried setting this src url ({{ url_for(\'static\',filename=\'images/facebook.png\') }}) inside the html template to see if maybe i had a typo, and i don't. When it's loaded into the html template the image loads just fine. But for some reason when i try to change the DOM from my JS file it doesn't want to work. I've looked everywhere for a similar problem. but nobody seems to have this same issue. I even saw a blog post of someone changing the dom through ajax the exact same way and it worked fine. Please help.
I am trying to work with handlebar templates, but it's not going so well.
In *.html.twig I have:
<script id="entry-template" type="text/x-handlebars-template">
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
</script>
<span id="demo">
</span>
<script>
var source = document.getElementById("entry-template").innerHTML;
var template = Handlebars.compile(source);
var context = {title: "My New Post", body: "This is my first post!"};
var html = template(context);
document.getElementById("demo").innerHTML = html;
</script>
And there is an error:
Variable "title" does not exist.
When I put this code in simple index.html w/o Symfony etc. it works. Any ideas how to fix it?
This is happening because Twig is also an HTML templating language which also uses {{ ... }} syntax to denote variables, just like Mustache is, so Twig is trying to parse it before outputting the HTML.
If you want to use Twig and Mustache together, then you'll need to escape/double-encode the curly braces that are intended for Mustache so that Twig doesn't try to parse them first.
There is a repo on Github which lets you define your own custom delimiters for Handlebar templates.
Can HTML from an ejs template be injected via JQuery?
I have an Index file that has a navbar and a content area, as well as a sample TestButton template that I am trying to render.
Index.ejs
<ul>
.
.
<li id="listItem">Nav Bar Item</li>
</ul>
<div id="display">
</div>
<script>
$('#listItem').click( function(){
// Note - testButtonTemplate is being properly passed in from my routes
$('#display').html( <%- render( testButtonTemplate, {} ) %> );
});
</script>
TestButton.ejs:
<a href="#" class="btn btn-primary" id="test-button">
Click Me!
</a>
I did my best to simplify my code, but basically, when I click on a link from the nav bar, I want to dynamically load a page in the display div.
The nav bar works.
The click functionality works.
If I manuallay display the ejs template in the div, it works.
EX:
<div id="display">
<%- render( testButtonTemplate, {} ) %>
</div>
Otherwise, when I try to load the page with the sample code above, this is the error I get:
"Uncaught SyntaxError: Unexpected token <" and the raw html looks like:
.
.
<script>
$('#listItem').click( function(){
$('#my-test').html( <a href="#" class="btn btn-primary" id="test-button">
Click Me!
</a>
);
});
</script>
So you can see that the html has been properly retrieved from the ejs template class, but JQuery does not like how I am formatting that data. It looks like the data needs to be surrounded in quotes, but simply adding beginning and end quotes does not solve the problem.
I have tried seemingly every combination of quotes, escaped and unescaped html, storing the data in a variable first then trying to inject it, but none are working for me.
Is there an obvious mistake I'm making? I would prefer to solve the problem given my current tool set.
Try loading your template like this:
<script>
var template = new EJS({url: '/TestButton.ejs'});
$('#listItem').click( function(){
$('#display').html(template.render());
});
</script>
I just started using Mustache and I like it so far, but this has me perplexed.
I am using the GitHub gist API to pull down my gists, and part of what I want to do is include the embedding functionality into my page. The problem is Mustache seems to not want to have anything to do with my dynamic script tag.
For example, this works fine:
<div class="gist-detail">
{{id}} <!-- This produces a valid Gist ID -->
</div>
Additionally, this works perfect:
<div class="gist-detail">
<script src='http://gist.github.com/1.js'></script> <!-- Produces the correct embed markup with Gist ID #1 -->
</div>
If I try to pull these together, something goes terribly wrong:
<div class="gist-detail">
<script src='http://gist.github.com/{{id}}.js'></script> <!-- Blows up! -->
</div>
Chrome Inspector shows this:
GET https://gist.github.com/%7B%7Bid%7D%7D.js 404 (Not Found)
... which looks like to me something is weird with escapes or whatnot, so I switch over to the raw syntax:
<div class="gist-detail">
<script src='http://gist.github.com/{{{id}}}.js'></script> <!-- Blows again! -->
</div>
And I get the same result in Inspector:
GET https://gist.github.com/%7B%7B%7Bid%7D%7D%7D.js 404 (Not Found)
How do I get the correct values to embed in the script tag?
EDIT
I am injecting the template as follows (in document.ready:
function LoadGists() {
var gistApi = "https://api.github.com/users/<myuser>/gists";
$.getJSON(gistApi, function (data) {
var html, template;
template = $('#mustache_gist').html();
html = Mustache.to_html(template, {gists: data}).replace(/^\s*/mg, '');
$('.gist').html(html);
});
}
The actually template is inside of a ruby partial, but it is wrapped in a div (not a script tag, is that a problem?) (that's hidden):
<div id="mustache_gist" style="display: none;">
{{#gists}}
<!-- see above -->
{{/gists}}
</div>
I assume a div is ok rather than a script because in either case, I'm pulling the .html(). Is this a bad assumption?
To avoid automatic escaping in Mustache use {{{token}}} instead of {{token}}.
It seems like your template is in HTML and trying to retrieve the template using html() results in a pre-URL-escaped template to be returned. Try placing your template inside a <script type="text/html"> tag instead.
When you embed your template inside an HTML element that excepts more HTML elements as children, it may get processed by the browser as HTML. Escaping may occur. By using a <script> tag with a non-script content type, you're basically telling the browser not to touch your template.
It looks like your script is getting requested before Mustache has a chance to update the src property. What you want to do is define the template in a way that it's not parsed as part of the DOM. A common approach is to define your template inside of a <textarea> tag. This will preserve formatting and prevent character escaping.
<textarea id="gist-detail-template" style="display:none">
<script src='http://gist.github.com/{{id}}.js'></script>
</textarea>
Now, to instantiate the template:
var template = $('#gist-detail-template').val();
var html = Mustache.to_html(template, yourTemplateData);
Here's an official example: http://mustache.github.com/#demo