Function call inside ngStyle gets sanitized - styles

I have a problem with style sanitization with Angular 8.
I've used ngStyle multiple times, but this time i cannot set the border of a td element.
I am trying to set the border style based on a field. If this field has a relevant content for me then i hilghlight it, otherwise i don't. I don't know the number of possible values of the field, neither the exact values: it's complitely dynamic, I only know my values of interest.
I'm returning the border style from a function inside the .ts file. Here are the code snippets:
<ng-container matColumnDef="{{cam}}">
<th mat-header-cell *matHeaderCellDef class="header"> {{cam}} </th>
<td mat-cell *matCellDef="let piano" class="cellaMagazzino" [ngStyle]=" {'border':shouldHighlight(piano[cam])}">
<div>
<!--content-->
</div>
</td>
</ng-container>
My typescript function looks like this:
shouldHighlight(element){
if (this.listaCommittenti == undefined && this.listaNumOrdine == undefined) {
let found = this.releventContentList.find(item => item.property == element.property)
let result = found != undefined ? '3px solid ' + this.myVariable["color"] : ""
return result
}
I used ngStyle calling functions other times, but in this case i get the error:
WARNING: sanitizing unsafe style value 3px solid rgb(241, 196, 15) (see http://g.co/ng/security#xss).
Is there some kind of configuration to do? is there a workaround?

Does this work for you?
Typescript:
getHighlightColor():string {
return "rgba(255,255,255,1)";
}
shouldHighlight(): boolean {
return true;
}
HTML:
<td mat-cell [style.border-color]="getHighlightColor(piano[cam])" [ngClass]="{ 'highlighted': shouldHighlight(piano[cam])}"
CSS:
.highlighted{
border-width:3px;
border-style:solid;
border-color:transparent;
}

In general, I would strongly advice against using function calls in your template as it's a real performance killer. It's much better to calculate the desired classes and add them to your data instead.
Federico's approach is a nice work around, however you could also use your orignal approach and bypass the style security via bypassSecurityTrustStyle(yourStyleString) see Trusting safe values

Related

Toggle pagination in ag-grid

Is there a way to dynamically toggle pagination in ag-grid?
The API doesn't seem to explicitly support it.
What's the best workaround?
As far as I know there is not nativly something available. But the best workaround would be to set the pagination attribute in the gridOptions and then have the entire table re-render. In Angular this would looks something like this: https://plnkr.co/edit/aRPG3X6sTeuKcqj1?open=app%2Fapp.component.ts
For the template:
<button (click)="togglePagination()">Toggle Pagination</button>
<ng-container #container >
</ng-container>
<ng-template #table>
<ag-grid-angular
style="width: 100%; height: 100%;"
class="ag-theme-alpine"
[columnDefs]="columnDefs"
[autoGroupColumnDef]="autoGroupColumnDef"
[defaultColDef]="defaultColDef"
[suppressRowClickSelection]="true"
[groupSelectsChildren]="true"
[rowSelection]="rowSelection"
[rowGroupPanelShow]="rowGroupPanelShow"
[pivotPanelShow]="pivotPanelShow"
[enableRangeSelection]="true"
[rowData]="rowData"
[gridOptions]="gridOptions"
(gridReady)="onGridReady($event)"
></ag-grid-angular>
</ng-template>
and the toggle function is doing the redraw
public gridOptions: GridOptions = {
pagination: true,
}
public togglePagination() {
this.gridOptions = {pagination: !this.gridOptions.pagination};
this.outletRef.clear();
this.outletRef.createEmbeddedView(this.contentRef);
}
You didn't specify if you use a framework or the native JS. But the redraw approach works in every framework and also natively just with a different syntax

XPath with text() to get specific text node

<td style="width: 40.42%;" id="ember193" class="lt-cell align-left ember-view">
<div class="inline-block ember-tooltip-target">
<i class="fa fa-fw fa-lg valid"></i>
<div id="ember195" class="ember-tooltip-base ember-view">
<div><!----></div>
</div>
</div>
UNIVERSITY OF VERMONT AND STATE AGRICULTURAL COLLEGE
(03-0179440)<!----><br>
<div class="fa fa-fw fa-lg"></div>
(UNIVERSITY OF VERMONT)
</td>
In the browser console, I execute this:
$x("//tbody/tr[2]/td[2]/text()[7]")
and I get the actual text node I am looking for (amongst other text nodes in td2) - is there a way to specify this in a Text<_> property attribute to get just this text node?
Currently, there is no attribute to get a value of child text node by index, only first or last. Anyway, I would try not to rely on child node index as it can vary. I would try to extract the number part from the given text.
You can do it with a help of 2 properties:
[FindByXPath("td")] // TODO: Change it to your <td> locator.
[GetsContentFromSource(ContentSource.ChildTextNodesTrimmed)]
private Text<_> OrganizationNameInfo { get; set; }
public DataProvider<string, _> OrganizationNumber => GetOrCreateDataProvider(
"Organization Number",
() =>
{
string organizationNameInfo = OrganizationNameInfo.Value;
return organizationNameInfo.Substring(1, organizationNameInfo.IndexOf(')') - 1);
});
OrganizationNameInfo property because of ContentSource.ChildTextNodesTrimmed returns "(03-0179440)(UNIVERSITY OF VERMONT)" value. So in OrganizationNumber property you can easily extract as a sub-string the part you need.
Another option can be to use Regex to extract the number part.

How can I render specific piece of data from my mongodb into my html?

It's my first project. I'm creating a website where administrator have the privilege to change home page texts. So I'm keeping all texts in a collection called "Texts" , each document has a text:value . When home page is rendered I use Texts.find() to return an array containing objects each has a "text" value. I link it to my home page using index.
Like this..
<h2>Texts[0].text</h2>, so if i have 100 texts I go all the way to <h2>Texts[100].text</h2>. and they are different texts and I need to put them in a specific order so I can't just throw them into my html.
I know that's so stupid , so I'm looking for some idea instead of this.
--------------Modification------------------>>>>
I tried using find method for arrays but it also is so tiring , so something simpler would be great , here's a portion of the code
<div class="card bg-dark text-white">
<img src="<%=imgsArr.find(x => x.name === 'main2').src%>" class="card-img" alt="...">
<div class="card-img-overlay ">
<h2 class="card-title"><%=textArr.find(x => x.id === 14).text%></h2>
<div class="triangle-up"></div>
<hr class="ml-0 ">
<div class="triangle-down"></div>
<p class="card-text "><%=textArr.find(x => x.id === 15).text%></p>
<div class="card-topic">
<h2 class="card-title" style=";"><%=textArr.find(x => x.id === 16).text%></h2>
<p class="card-text"><%=textArr.find(x => x.id === 17).text%></p>
</div>
<div class="card-topic">
<h2 class="card-title" style=""><%=textArr.find(x => x.id === 18).text%></h2>
<p class="card-text"><%=textArr.find(x => x.id === 19).text%></p>
</div>
<div class="btnOut ">
<button class="btn btn-lg shadow-lg ">MENU</button>
</div>
</div>
</div>
Good news is that for loops are always a good option. If you are using ejs or a similar rendering engine something like this should work, although you will have to tweak it a bit. Take a look are the EJS rendering engine documentation for an exact format, but it would look something like below and no matter how long the list gets it will render as much as it receives(if it is a lot you might want to consider using pagination)
<% for text in Texts.text %>
<% if text==="some value"%>
<h2>text</h2>
<% else %>
<p> text </p>
If your front-end is perhaps react.js or vue.js or similar the same prnciple would work but the format will be different.
No offense friend but you need to get some tutorials. But let me help you as best i can. Everything in a web application is somewhat defined. Meaning it falls into one predetermined category or another. When you get json for example you get something base on how that particular data is defined in the database. Hence you can get json data from your backend that looks
{ 'title':'sneaker', 'price':'200', 'quantity':'50' }
Now assuming it is a list of json objects what you can do is loop through this and assign them to tags based on their object key(because it gets converted to a javscript object). so again you code would look something like
<% for text in Texts.text %>
<h2>text.title</h2>
<div>
<p>text.price</p>
<p>text.quantity</p>
</div>
This would be how you would render data from your database(the format might not exactly be spot on). Dealing with forms is a whole other ball game. So get a book or some tutorial videos that discuss it. You will better understand how to handle it.
For your code you are being very rigid, at first glance there is already a pattern, work with that pattern, you code just needs a simple for loop from what i gather.
for(let i=0; let i>100; i++){
if (i%2===0){
console.log(<h2> i </h2>)
}else{
console.log(<p> i </p>
}
}
The reason i have resulted to pure javascript is so you can see what the inner workings of your render should look like. You can get the total number of ids in your database(that is what the integer 100 represents in this case), loop through one by one and produce what you want. It is still javascript, do not let the html throw you off

Conditionally render depending on presence of a faces message

I have a special row in my table for errors:
<tr>
<td colspan="2"><p:message for="questionId" id="msgQuestion" /></td>
</tr>
How can I set this so the row is only displayed when there is an error?
In first place i will recommend not to use table to display layout elements
after that the ellement will apear even if the message is not present, if you are obliged to use it you can use som think like this in JS:
<script type="text/javascript">
window.onload = function() {
hideTdMessage();
};
hideTdMessage(){
var message = document.getElementById(msgQuestion);
if(message){
//the msg is present
}else{
//the msg is not present
}}
</script>
Or You can use your MBean to change the CSS class it's better than using JS.
But i will say that the best solution is not tu use the tabel.
Hope it helped
Use a JSF component and the property rendered
rendered="#{not empty facesContext.messageList}"

In YUI determine if an element exists that has a specific value

I'm fairly familiar with jQuery, but I'm working on a project in YUI, which I am totally new to, and am not sure how to accomplish this.
In essence, I need to display a js popup if a span element exists that has the text "Inactive" in it and is several steps down the tree from a div with a class of "list_subpanel_cases".
This is a rough example, but the point is, this is dynamically built, so my only definite selectors are the div with the class and the descendant span with a text value of "Inactive".
<div class="list_subpanel_cases">
<table>
<tbody>
<tr>
<td>
<span>Active</span>
</td>
</tr>
<tr>
<td>
<span>Inactive</span>
And I need to find out if any spans exist with the text "Inactive".
Hope this isn't too confusing!
It appears that CSS3 selectors can't examine content (only attributes) so you'd have to use a selector for the candidate span tags and then use code to look at the content for a match. Here's one way to do that:
function findInactive() {
var found = null;
Y.all(".list_subpanel_cases span").some(function(node, index, nodeList) {
if (node.getContent() == "Inactive") {
found = node;
return(true); // stop looking for more matches
}
return(false); // keep looking for more matches
});
return(found);
}
if (findInactive()) {
// execute code here when the Inactive span exists
}
You can see it work here: http://jsfiddle.net/jfriend00/BVzqL/.

Resources