How to escape html encoding in detail template of kendo grid - kendo-grid

I have a kendo grid with detail template. This is kendo MVC grid. I get some data from server which will have html text.
lets say parent grid data is like this "<span class='text-red'>Test</span>"
In parent grid I am binding this column like this.
columns.Bound(m => m.Name).ClientTemplate("#if(Name=== ''){# - #}else{# #=Name# #}#");
This will give me output Test
In detail template of this grid I get some other data using child grid Read method which also has some html data. Let says child grid gets "<span class='text-green'>Hi</span>"
I am binding this data like this.
columns.Bound(m => m.ChildName).ClientTemplate("\\#if(ChildName== ''){\\# - \\#}else{\\# \\#=ChildName\\# \\#}\\#")
but this is giving me output as <span class='text-green'>Hi</span>but I want output as just Hi. Why it is showing entire html? Why not it treat same as parent grid? I want the text Hi with css applied just like parent grid

Solved. The child grid Read call encoding the html. I am getting data as "<span class=''>Test</span>" etc. So I modified child grid clientTemplate to call java-script function which will give correct data.
columns.Bound(m => m.ChildName).ClientTemplate("\\#=escapeNameEncode(ChildName)\\#")
JavaScript function
escapeNameEncode(name: string) {
if ($.trim(name) == '') {
return '-';
} else {
var decodedString = $('<div>').html(name).text();
return decodedString;
}
}

Set .Encoded(false) to your drill down column:
columns.Bound(m => m.ChildName).ClientTemplate("\\#if(ChildName== ''){\\# - \\#}else{\\# \\#=ChildName\\# \\#}\\#").Encoded(false)

Related

Playwright; asserting nested `img src` values

Note, this is related to my previous question here: https://stackoverflow.com/a/73043433/4190664
I am looking to further assert somethings within the DOM when I click the 'Print' button.
From troubleshooting I am seeing the following:
the pdfjs page has a #printContainer that is an empty div
when you click the Print button, it begins creating divs with the class .printedPage to represent each page of the document
within each .printedPage div is an img element with src="blob:https://mozilla.github.io/**"
Example when the print dialog is open:
<div id="printContainer">
<div class="printedPage"><img src="blob:https://mozilla.github.io/5afcff4c-aa36-4118-b4b8-011cdce6a9bc"></div>
<div class="printedPage"><img src="blob:https://mozilla.github.io/30cd3036-2d81-4b82-af9a-0f2e9c834b69"></div>
<div class="printedPage"><img src="blob:https://mozilla.github.io/047e8762-3fae-44d1-a5a0-56ea576de93e"></div>
</div>
I already am testing the following:
let requestCount = 0;
page.on('request', request => {
if(request.url().includes('blob:https://mozilla.github.io/pdf.js/web/viewer.html')) {
expect(page.locator(`.printedPage img >> nth=${requestCount}`)).toHaveAttribute('src', /blob:https:\/\/mozilla.github.io/);
requestCount++;
}
});
await printBtn.click();
await expect.poll(() => requestCount).toBe(3);
What would be the best way to assert that each .printedPage > 'img' src contains the blob information as well?
Playwright (and javascript in general) is not a strong language so I am definitely struggling on this one 😬
Any syntactical help is appreciated
You can do something like this. You can add this before the value of requestCount increments.
await expect(
page.locator(`.printedPage img >> nth=${requestCount}`)
).toHaveAttribute('src', /blob:https:\/\/mozilla.github.io/)

How can I use Render sub-template in a C# template in a Content module that uses lists within lists?

2SXC 10.25.2 / DNN 9.3.2
I have a 2sxc module that uses a C# template with "list" enabled. I have a content type called "pathway" and inside that I have 2 entity picker fields for "first step sessions" and then "next step sessions". These entity pickers use a "session" content type. Inside each of those "session" content types I also have an entity picker for "speaker(s)". All in all, it's a setup that I have lists within lists within lists.
When I create the loops for each of the sublists, I can easily do that within the 1 C# template but it becomes repetitive, long, and unruly because there's so much c# code where I'm looping the same session template for different entity picker sections. So, I tried using the "Render sub-template" code to simplify the template - I created new sub templates and inserted them in - it seemed to work at first, however, the template started outputting all "session" items into each item in the list.
I suspect that the subtemplate somehow loses the context of the item that it's in so it's outputting everything. Is there something special I need to know about using subtemplates with for each loops? Do I have to include params and, if so, how do I do that?
EDIT to include code sample:
Here is a small, simplified version of the code I'm working with:
#foreach(var Content in AsList(Data)) {
<h2>#Content.Title</h2>
<h3>Lead Sessions</h3>
<div class="lead-sessions text-green">
#foreach(var item in AsList(Content.LeadSessions as object)){
<h4>#item.LeadSessionTitle</h4>
<p>#item.LeadSessionText</p>
}
</div>
<h3>Next Sessions</h3>
<div class="next-sessions text-green">
#foreach(var nextitem in AsList(Content.NextSessions as object)){
<h4>#nextitem.LeadSessionTitle</h4>
<p>#nextitem.LeadSessionText</p>
}
</div>
}
I want to make a subtemplate so I don't have to repeat the same code for the sessions loop. How could I simplify this template to use a subtemplate for looping the sessions within the lead-sessions and next-sessions?
So based on the modified question, it's a bit like this
#foreach(var Content in AsList(Data)) {
<h2>#Content.Title</h2>
<h3>Lead Sessions</h3>
#RenderPage("_inner.cshtml", new { Items = Content.LeadSessions })
<h3>Next Sessions</h3>
#RenderPage("_inner.cshtml", new { Items = Content.NextSessions })
}
Second file _inner.cshtml
#{
var items = AsList(PageData["Items"]);
}
<div class="next-sessions text-green">
#foreach(var nextitem in items){
<h4>#nextitem.LeadSessionTitle</h4>
<p>#nextitem.LeadSessionText</p>
}
</div>
Yep, you can just use RenderPage without params, or pass in params like in the blog app:
#RenderPage("shared/_Category Filter.cshtml", new { MobileView = true, FilteredCategory = filteredCategory })
See https://github.com/2sic/app-blog/blob/master/_List.cshtml#L25
Then the template can retrieve the values like
#{
var filteredCategory = PageData["FilteredCategory"];
}
See https://github.com/2sic/app-blog/blob/master/shared/_Category%20Filter.cshtml#L6
You can pass around any amount of values/objects like this.
You can also create helpers - and then call those helpers. Like this
https://github.com/2sic/app-news/blob/master/shared/_Helpers.cshtml#L24-L33

How to compile/add HTML inside md-tooltip

I am trying to add HTML inside an md-tooltip but haven't had any luck, even with ng-bind-html.
Without using ng-bind-html, the tooltip outputs:
Some html<br>
<strong>card</strong>.
With it, my HTML outputs as a string:
Some html<br><strong>card</strong>
In my controller, I use this custom filter to compile HTML used within an ng-repeat:
app.filter('unsafe', function($sce) { return $sce.trustAsHtml; });
This filter successfully works with other elements aside from tooltips.
The tooltip is written as:
<md-tooltip md-delay="1000" md-direction="bottom" class="tooltip-sort-display">
<span ng-bind-html="categoryItem.ToolTip | unsafe">
</md-tooltip>
Please note, when I don't use a json variable and instead add static text to the tooltip, HTML has no trouble rendering
<md-tooltip md-delay="1000" md-direction="bottom" class="tooltip-sort-display">
<strong>Tool</strong><br><em>tip</em>
</md-tooltip>
Any ideas on how I can make this work? I would put together an example, but my Angular skills aren't that advanced. I mainly do the front-end development off my colleagues' work.
In your case, your problem is that you are using HTML special chars. If not, your code will works fine. Anyways if you cannot avoid receive special chars, you can add the decode in your filter:
JSFIDDLE DEMO
.filter('unsafeSpecial', function($sce) {
return function(value) {
var txt = document.createElement("textarea");
txt.innerHTML = value;
return $sce.trustAsHtml(txt.value);
}
})
And the you can use like this way:
HTML
<md-tooltip>
<span ng-bind-html="msg | unsafeSpecial"></span>
</md-tooltip>
CONTROLLER
.controller('mainCtrl', function($scope) {
$scope.msg = 'Some html<br><strong>card</strong>';
})
For more info about decode html topic, check this question if you want: HTML Entity Decode

JQuery selectors - using html snippets as "context" in filter and find

A quick question about using context with Jquery selectors:
I'm trying to grab the text from a div element that has id="time". Can a HTML snippet be used as context in the following:
// An AJAX request here returns a HTML snippet "response":
var myTime = $("#time", response).text();
The reason I'm doing this is that I want the time variable from within the html held in response, but don't want the overhead of loading all of the html into the DOM first. (it's a large amount of html).
From the comments what I understand is the response is <span id="time">blah blah</span> which means the element time is the root variable itself, that is why the child lookup is not working.
var response = '<span id="time">blah blah</span>';
var myTime = $(response).text(); // Or $(response).filter("#time").text();
alert(myTime)
Demo: Fiddle
This method uses filter() rather than find(), the difference being:
filter() – search through the passed element set
find() – search through all the child elements only.
Did you try it?
$("#time", "<div><span id=time></span></div>")[0].id //returns 'time'
From the jQuery source code:
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
return this.constructor( context ).find( selector );
}
so valid selectors should work in the context parameter. Personally, I prefer using find to begin with because it keeps all the selectors in the same order instead of $("second > third", "first");

jqPlot charts on page load

I have a form where I select the number of items. Upon clicking submit, it should take me to a new page where it would display the item selected and depending on the number of items selected, it would create those many jqPlots, one for each item.
Any suggestions on how do I go about doing this?
Thanks,
S.
It's hard to give any specifics without more detail about the items, but basically you would pass a JSON structure to your view with the items to be plotted. Then you would loop through the JSON structure, creating DIV tag for each item to be plotted and appending the DIV tags to the body.
The Javascript part would look something like this:
$.each(items, function(index, value) {
$myPlot = $("<div>");
$myPlot.attr("id", "item"+index);
$.jqplot($myPlot.attr("id"), ...);
$("body").append($myPlot);
});
This question is very general, but answering (specifically and only) the question of loading multiple charts:
You need a unique HTML div id for each chart; consider using an RFC 4122 UUID (generate as needed) for each chart/div rather than a sequential index for each. Use something that looks like this as a placeholder div for each:
<div class="chartdiv" id="chartdiv-${UID}">
<a rel="api" type="application/json" href="${JSON_URL}" style="display:none">Data</a>
</div>
This embeds the JSON URL for each div inside it, in a hidden hyperlink that can be discovered by JavaScript iterating over your multi-chart HTML page.
The matter of the UUID is inconsequential -- it just seems the most robust way to guarantee a unique HTML id addressable by JavaScript for each chart.
Subsequently, you should have JavaScript that looks something like:
jq('document').ready(function(){
jq('.chartdiv').each(function(index) {
var div = jq(this);
var json_url = jq('a[type="application/json"]', div).attr('href');
var divid = div.attr('id');
jq.ajax({
url: json_url,
success: function(responseText) { /*callback*/
// TODO: responseText is JSON, use it, normalize it, whatever!
var chartdata = responseText;
jq.jqplot(divid, chartdata.seriesdata, chartdata.options);
}
});
});
});