I have a blade template that has some HTML and some JS code. For both case 1 and 2 I'd like to use the same template as it's used in multiple places.
Case 1: include the template with the normal behaviour, so that the code in the template gets executed. This works with the normal behaviour of using #include('template')
Case 2: include the template without the HTML and JS actually being interpreted.
Now I could solve this by making it an x-template component, and then pass a variable to that component that will conditionally wrap the template in <xmp></xmp>.
But the problem is that I use Highlightjs, and that doesn't work if the code is in those xmp tags. It needs to be in <pre><code></code></pre>.
So I'm wondering if you can pass some parameter or do something to include a blade template without actually interpreting the code that's being included.
Update
A bit more clarification. Let's say template.blade.php has this:
<div id="test"></div>
<script>
alert('test');
</script>
In case 1 using #include('template') should alert test when the page is loaded.
In case 2 using #include('template') (but then another way I guess, that's what this question is about) I'd like it to display the code without interpreting it, like would happen when using <code>{{ '<div id="test"></div><script>alert('test');</script>' }}</code>.
Related
I know that you can change the default blade delimiter using
Blade::setEscapedContentTags('[[', ']]');
Blade::setContentTags('[[[', ']]]');
However I don't know where should I put it so that it only affect single blade template as opposed to putting it at app/start/global.php which affect whole application.
If you only want to use different tags for a single view, you can set the tags in the closure or controller action that will generate the view.
Route::get('/', function()
{
Blade::setEscapedContentTags('[[', ']]');
Blade::setContentTags('[[[', ']]]');
return View::make('home');
});
This could be an issue if you want to use the normal tags {{ and }} in an application layout but your custom ones in a nested view - I'm not sure what the best approach there would be.
The solution with Blade::setEscapedContentTags / Blade::setContentTags doesn't work in the latest versions of Laravel (checked at 5.6).
The recommended approach is (https://laravel.com/docs/5.6/blade#blade-and-javascript-frameworks):
Blade & JavaScript Frameworks
Since many JavaScript frameworks also use "curly" braces to indicate a
given expression should be displayed in the browser, you may use the #
symbol to inform the Blade rendering engine an expression should
remain untouched. For example:
Hello, #{{ name }}.
In this example, the #symbol will be removed by
Blade; however, {{ name }} expression will remain untouched by the
Blade engine, allowing it to instead be rendered by your JavaScript
framework.
The #verbatim Directive
If you are displaying JavaScript variables in
a large portion of your template, you may wrap the HTML in the
#verbatim directive so that you do not have to prefix each Blade echo
statement with an # symbol:
#verbatim
<div class="container">
Hello, {{ name }}.
</div>
#endverbatim
Simply use #verbatim directive.wrap your whole code in it and blade will just ignore all the curly braces.
Would there be bad consequences from transporting JSON in HTML like this:
<div id="json" style="display: none;">{"foo": "bar"}</div>
assuming HTML chars such as < are escaped as < in the element text?
The JSON could be strictly parsed:
var blah = $.parseJSON($('#json').html())
in a try/catch statement, for example. The rationale is to enable passing of JSON in Ajax'd HTML responses, when script tags are being stripped an not executed. An example would be Ajax requests made using the jQuery .load() special selector syntax:
$('#here').load('some.html #fragment')
...which ditches all script tags and thus prevents the use of:
<script>var blah = {"foo":"bar"}</script>
I've seen JSON being passed around in HTML attributes, and I'd guess this is equivalent - w.r.t. weirdness, security, etc - but is far less readable due to all the additional quote-escaping.
The natural way of passing JS data in HTML is through JavaScript code (if is a part of actual JavaScript code, like in the case of initial values/configuration) or by data- HTML5 attributes (whenever JS code is not necessary; always when data needs to be somehow attached to DOM elements).
In your example this would be probably the best:
<div id="json" style="display: none;"
data-something="{"foo":"bar"}">
</div>
but reorganize your data to actually follow HTML structure:
<div class="profile-container"
data-profile="{"name":"John Doe","id":123}">
... profile 123 ...
</div>
<div class="profile-container"
data-profile="{"name":"Jane Doe","id":321}">
... profile 321 ...
</div>
(quoting should be done server-side, eg. using PHP's htmlspecialchars(...), or Python's cgi.escape(..., True)).
And then you can obtain the data in one of multiple ways, eg. using jQuery's .data() method.
EDIT:
Yes, your approach with embedding JSON as content of HTML tags and hiding it using CSS styles has gotchas. As I said, if you want to pass data in HTML, the only "best practice" way is to attach it to one of HTML elements (you are kind-of doing it anyway, but you use CSS to hide it, while you can use existing solutions for passing JSON/data without affecting clients that could override your styles). The proof for one of disadvantages is here: http://jsfiddle.net/NY7Bs/ (data is passed both ways, but one simple external style overrides your inline styles and shows the content - not mentioning the influence on semantics of your document).
Why not simply use the .ajax() function then, you would get only the string with the json. Then you could parse it as you suggested.
Background Smarty is a templating engine that separates the presentation layer from the logic layer of web applications. It is well-suited for the Model-View-Control approach to developing web applications. The View can be represented by Smarty templates, which contain only HTML and Smarty tags. The Control can be implemented by PHP files that serve the appropriate views based on the logic contained within them via PHP code. The View is instantiated by displaying the templates via the display() command. Alternatively, a template can be read in as a variable without displaying it via the fetch() command. The file name of the template is the argument to both these commands.
Issue The fetch() command can read an entire template. In order to read parts/sub-parts of a template, each of these parts would normally needed to be stored in a separate file with its own name that can be the argument to the command. This creates needless files.
Question Is it possible to fetch only parts of a Smarty template by somehow marking sections of the template?
Case example Below I present a sample template file with Smarty and HTML tags, as well as the corresponding controller file with PHP code.
Template file (index.tpl)
<html>
<body>
<div id="sec1">
First section
</div>
<div id="sec2">
Second section
</div>
</body>
</html>
Controller file (index.php)
<?php
$smarty = new Smarty;
$template = $smarty->fetch("index.tpl");
?>
In the example above, the $template variable would contain the full output from the template page. Below is a dump of its contents from the example.
$template => string(255)
"<html><body>
<div id="sec1">First section</div>
<div id="sec2">Second section</div>
</body></html>"
However, suppose I wish to read in the code from each of the DIV containers separately, and store them into separate variables, how could I achieve this? For instance, suppose I have a magical function called fetch_sub(). Here's my expectations of using it.
<?php
$smarty = new Smarty;
$div1 = $smarty->fetch_sub("index.tpl", "sec1");
$div2 = $smarty->fetch_sub("index.tpl", "sec2");
?>
Then $div1, etc would contain only the relevant sub-part, instead of the whole template.
Other info I am not a beginner with Smarty and have a fairly good handle on basic concepts, as well as some of Smarty's advanced concepts. Following is my attempts so far at conceptualizing the problem and getting to a solution. My initial rough idea is to demarcate the template into sections using {capture}, and then somehow reference each of these sections. I present an outline example of the idea below.
{capture name=sec1}
<div id="sec1">
First section
</div>
{/capture}
. . .
Smarty (as of Smarty 3.1) has no built-in feature to allow you achieving your goal. I had proposed something similar in 2011, but we haven't come around to implementing it.
Maybe you can have the generated HTML parsed to DOM and help yourself with xpath, or something like that?
You can try this:
sec1.tpl
<div id="sec1">First section</div>
sec2.tpl
<div id="sec2">Second section</div>
index.tpl
<html><body>
{include file="sec1.tpl"}
{include file="sec2.tpl"}
</body></html>
And then You can fetch parts by invoking:
$smarty = new Smarty;
$div1 = $smarty->fetch("sec1.tpl");
$div2 = $smarty->fetch("sec2.tpl");
Actually the question is in the subj...
Is it possible to make handlebars template framework, to recognize templates within a div tag and not in script tag?
For example I would like to create template with this markup:
<style>
div.text-x-handlebars {display:none;}
</style>
<div class="text-x-handlebars-template">
<h2>I'm template</h2>
<p>{{welcomeMessage}}</p>
</div>
Yes you can put your templates in <div>s rather than <script>s, for example:
http://jsfiddle.net/ambiguous/RucqP/
However, doing so is fraught with danger. If you put your template inside a <div> then the browser will interpret it as HTML before you've filled it in; so, if your template's HTML isn't valid until after it has been filled in, the browser may attempt to correct it and make a mess of things. Also, if you have id attributes in your templates, then you will end up with duplicate ids (one in the template <div> and a repeat in the filled in template that you put in the DOM) and that will cause all sorts of strange and interesting bugs. The browser will also try to download any images inside the templates in a <div>, this may or may not be a problem (if might even be desirable but probably not desirable if the image uses a template variable in its src attribute).
Basically, you can do it but you shouldn't, you should put your templates in <script id="..." type="text/x-handlebars-template"> elements instead.
I hava an editor template for, let's say, date:
#model DateTime
#section AdditionalJavaScript2
{
/* some js code */
}
#Html.TextBox("", Model.ToString("d.M.yyyy"), new { #class = "date" })
Now, I would like to put some js code into the HEAD section, but this doesn't work.
Of course, I have a this section in my layout.cshtml:
<head>
...
#RenderSection("AdditionalJavaScript2", required: false)
</head>
It works from the plain view, but not from partial view (editor template).
Why?
And, is there a workaround?
Thanks,
Igor
A partial-view does not use a template, it returns "raw" html to be included in your page (by Javascript). It does not have access to anything but the stream it returns itself.
Think of it like this: You typically call a partial view from Javascript/AJAX to get some new html. You get the return, and replace some DIV-tag. How can the system (FireFox, Chrome, ...) know, that there is some extra section of data that needs to replace something in the HEAD tag.
There are some workarounds:
Don't put the script in the HEAD
Add a parameter switch betweed the html and the script. You need to client-side calls, one to get the html, and one for the script. You include the calls to the partial-view on two locations on your page.
Separate the script and the html using some pre-defined tag like <!-- SEPERATOR -->, and let the calling code split the result, and put it in the correct position.