Accessing Tag Helper output in Javascript - asp.net-core-mvc

beginner question with Razor and tag helpers I'm afraid!
Using tag helpers in my razor html, I can e.g. write:
<div><date-picker id="datepicker" value="#DateTime.Now"></date-picker></div>
This will then generate the output
<input id="datepicker" class="datepicker" aria-atomic="true" aria-live="assertive" aria-expanded="false" role="combobox" name="datepicker" placeholder="Select date">
and so on. What I'd like to do is to append the output to other objects like dialog screens, which accept an html string to append.
e.g.
var customDesign = "<div id="something"><date-picker id="datepicker" value="#DateTime.Now"></date-picker></div>";
$(".myDialogfield").after(customDesign);
This doesn't work in Razor - I've tried various things like creating this as a HTML.Raw string first and injecting it as a variable etc - is there a way I can use the output from my tag helper within a script section?
Thanks for any hints!

You can't do it that way. TagHelpers are interpreted. In other words, Razor must see them as actual tags in order to replace them. Here, it's just a JS string, and Razor will not mess with that.
Your best bet would likely to be some sort of JavaScript templating system, but generally speaking you could still get what you want manually via a different path. Instead of hardcoding a string of HTML, include the TagHelper in a script block of type text/html:
<script type="text/html" id="MyTemplate">
<date-picker id="datepicker" value="#DateTime.Now"></date-picker>
</script>
Then, in your JavaScript, you can select this script tag and get its content:
var customDesign = $('#MyTemplate').html();
$(".myDialogfield").after(customDesign);

Related

Bind raw html in Aurelia

Using Aurelia, I want to fill an <div> with contents of viewmodel property (lets call it htmlText) which contains html text, and I was using
<div>
${htmlText}
</div>
However, this encodes html so, instead of i.e. having paragraph or link, all tags are escaped so html can be seen as source.
Is there out of the box binder to do this?
You can accomplish this using the innerhtml binding like so:
<div innerhtml.bind="htmlText"></div>

How to Use JavaScript instead of Custom HTML Attributes for Angular Forms?

Considering this example markup (from http://www.ng-newsletter.com/posts/validations.html):
<div class="row">
<div class="large-12 columns">
<label>Your name</label>
<input type="text"
placeholder="Name"
name="inputNameAttributeValue"
ng-model="signup.name"
ng-minlength=3
ng-maxlength=20 required />
<div class="error"
ng-show="signup_form.name.$dirty && signup_form.name.$invalid">
<small class="error"
ng-show="signup_form.name.$error.required">
Your name is required.
</small>
<small class="error"
ng-show="signup_form.name.$error.minlength">
Your name is required to be at least 3 characters
</small>
<small class="error"
ng-show="signup_form.name.$error.maxlength">
Your name cannot be longer than 20 characters
</small>
</div>
</div>
</div>
Is there a way to accomplish the same thing, but use JavaScript instead of custom Angular attributes?
For example, is there a way I can use JavaScript instead of these Angular html attributes: ng-model, ng-minlength, ng-maxlenth, ng-show?
EDIT:
Just to clarify, I'm looking for a solution that uses the Angular JavaScript API. I would like to have a separate JavaScript document (linked from my HTML document) that uses the Angular JavaScript API. For example, is there a way to specify ng-model for a particular form field using the Angular API instead of the custom Angular HTML attribute?
As I understand it, you want to add a directive (for example ng-model) from javascript, similar to how you would do it with jQuery. Short answer: Don't do it.
Longer Answer: It's probably technically possible, but it would violate the basic principles of AngularJS. Your controller should not touch the HTML at all, in fact any code which should directly manipulate the HTML should be placed in a directive. And that directive should be placed on the input directly in your HTML, which is exactly what you wanted to avoid.
If placing directives in your HTML is not practical for your project, then perhaps you should reconsider using AngularJS.
There's a rather long (and well written) answer here on Stackoverflow which explains "how to think in AngularJS", you might find that it's of interest: https://stackoverflow.com/a/15012542/179024
It would also be interesting to know why you want to do this? There is often an "Angular way" of doing things, but it can be different from what we are used to doing.

Passing JSON as HTML element text

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.

How to fetch() sub-parts of a Smarty template

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");

Handlebars template with "div" tag instead "script"

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.

Resources