Kendo Template anchor tag - kendo-grid

How do I have the variable value be in an anchor tag in my grid column server template?
.Columns( columns=>
{
columns.Bound(c =>c.Text).Template(#<text href='home/index/#=Text#'><a></a></text>);
})

The simplest way of doing this is changing it to use the ClientTemplate rather than template like so:
.Columns( columns=>
{
columns.Bound(c =>c.Text).ClientTemplate("<a href='home/index/#=data.Text#'>#=data.Text#</a>");
})
If you have something a bit more advanced then pulling this out into either a function or a kendoTemplate will make life a lot easier.

Related

How to pass data with Html Attributes after mapped Array without using another React components?

I am trying to pass data with HTML attribute without using another component to handleClick but I couldn't handle can anyone help me please
const handleLiClickFirst = (airport) => {
setFirst(airport.target.innerHTML);
console.log(airport.target.lat); // I can't read the data here
};
<div className="header__first">
<TextField
id="outlined-basic"
label="From"
variant="outlined"
value={first}
onChange={(e) => setFirst(e.target.value.toLocaleLowerCase())}
/>
<ul>
{resultFirst.airports?.map((airport, i) => {
return (
<li
key={airport.iata}
airport={airport}
onClick={handleLiClickFirst}
lat={airport.latitude}
name={airport.name}
long={airport.longitude}
>
{airport.name} // I can read the data here
</li>
);
})}
</ul>
</div>
Random attributes like airport and lat aren't valid to attach to a native HTML element like <li>. However, you should be able to use data attributes instead to store data on an HTML element.
And you will likely need to use data-airport={JSON.stringify(airport)} instead of just passing the JS object. And if you can avoid passing the entire object in, (by saving each of the properties that you need separately, like you are already doing with latitude, for example) that may be best to avoid to prevent creating massive HTML attribute strings.
I solve this problem without attributes and the handleClick Method after I couldn't reach the data. I removed handleClick from onClick and added the code in onClick
onClick={() => {
setFirst(airport.name);
// setFirstLatlong([airport.latitude,airport.longitude]);
setFirstLatlong({
lat: airport.latitude,
long: airport.longitude,
});
}}
#Jacob K I will try to use your method on an upcoming project. Thank you

How to prevent passing className and style props to component in React

Hi I have a custom button component. This button component should accept all ButtonHTMLAttributes except for className and style to prevent devs from adding their own styles. I am using TypeScript with React. How can I achieve this? I tried using Omit but it's not working.
I think what you can do is you can overwrite the styles and classNames properties like:
function CustomButton = (props> => {
return (
<button {...props} className={""} style={{}}/>
)
}
I don't know how you annotated types. But you can try the rest parameter concept.
function Button({className, style, ...restProps}) {
// Use the restProps object
}

How do you generate dynamic <style> tag content in Angular template at runtime?

I have an Angular component that generates mat-checkbox dynamically at runtime and I need to change the individual background of each checkbox differently with different color and I don't (won't) have the information before hand, only available at runtime.
I have the following ng-template for the checkboxes:
<ng-template #renderCheckbox let-id="id" let-attr="attr">
<mat-checkbox
[checked]="attr.show"
[color]="'custom-' + id"
(change)="onChange($event.checked, attr)">
{{attr.name}}
</mat-checkbox>
</ng-template>
where, attr in the template has the following interface type, these infomation are pulled from Highcharts' series and I didn't want to hardcode the color.
interface LinkedSeriesAttributes {
id: string;
name: string;
index: number;
color: string;
checked: boolean;
}
Since there is no way to create css classes before hand and there is no way to directly apply color to the mat-checkbox, I could only generate the <style>...</style> right at the beginning of my template.
In my component, I have code that will generate the style which would give me something like this:
.mat-checkbox.mat-custom-hello.mat-checkbox-checked .mat-checkbox-background::before {
color: #6E8BC3 !important;
}
.mat-checkbox.mat-custom-world.mat-checkbox-checked .mat-checkbox-background::before {
color: #9ED6F2 !important;
}
...
However, I tried various ways to dump it inside <style> without success. I tried:
<style>{{ dynamicCSSStyles }}</style>
Which, my IDE shows that's an error with the curly braces, although it compiled fine and ran without errors, I got nothing, can't even see the <style> tag.
I also tried to include <style> inside my dynamicCSSStyles variable, and angular just dumped the whole thing out as text...
What's the correct way to generate a <style> in Angular.
I've found a REALLY dirty way of "making this work" but it causes Angular to keep adding the <style> back into the DOM.
First, set encapsulation to ViewEncapsulation.None.
Second, create a function to generate the <style> tag the old fashion way with an id:
updateDynsmicStyleNode() {
const id = 'dynamic-css-styles';
const nativeElm = this.elmRef.nativeElement;
const existing = nativeElm.querySelector(`style#${id}`);
if (!existing) {
const styleTag = document.createElement('style');
styleTag.setAttribute('id', id);
styleTag.innerHTML = this.dynamicCSSStyles;
nativeElm.prepend(styleTag);
} else {
existing.innerHTML = this.dynamicCSSStyles;
}
}
Third, call our function in ngAfterViewChecked:
ngAfterViewChecked() {
this.updateDynsmicStyleNode();
}
I mean while this worked, it is really bad, since moving the mouse around the screen would cause Angular to just continuously reinsert the <style> tag.
Does anyone know some other way more legit to archive this? LOL
You can use ngClass or [class] attribute. Since you can have the styles ready from the component.ts file.
You can do something like this:
Way 1: If you already know what the dynamic ids might be, (like if it always will be 'hello' and 'world')
let dynamicClasses = {};
// Once you get some classes from your logic, you can add them to the object above
dynamicClasses['hello'] = 'custom-hello';
dynamicClasses['world'] = 'custom-world';
// Then in HTML
<mat-checkbox [ngClass]="dynamicClasses"></mat-checkbox>
Way 2: If you dont know what the classes also might be, like if its not always be hello or world, then create a method and call it where required, you might need to do something similar to #codenamezero said.

How to proper update UI when a property changes in Angular 5

I am trying to update UI automatically, avoiding jQuery. I just want to update a css of a button after a click happened.
Should it be done in html with inline javascript code or typescript component?
Right now I am evaluating the latter, handling CSS in typescript as follows.
The component which changes its alreadyLiked property:
sendLike(recipientId: number) {
this.userService.sendLike(fromUserId, this.user.id).subscribe(data => {
this.alertifyService.success('You have liked ' + this.user.name);
// any way to update UI without this trash?
const btnLikeMe = <HTMLInputElement> document.getElementById('btnLikeMe');
btnLikeMe.classList.remove('btn-primary');
btnLikeMe.classList.add('btn-success');
btnLikeMe.classList.add('active');
btnLikeMe.disabled = true;
}, error => {
this.alertifyService.error(error);
});
}
After alreadyLiked is changed, I would like to update btnLikeMe css automatically in HTML:
<button id="btnLikeMe" class="btn" (click)="sendLike(user.id)"
[disabled]="alreadyLiked"
[ngClass]="alreadyLiked ? 'btn-success active' : 'btn-primary'"
title="{{alreadyLiked?'You already liked me. Thank you' : 'Like me now!'}}">
Like
</button>
It is working but it seems to be a bad approach.
I am using "#angular/core": "^5.2.0"
You don`t need JQuery for this. NgClass is the right way.
NgClass adds and removes CSS classes on an HTML element.
In some point if you want do to more complex things you can call functions...[ngClass]="getClass()"
Then you can debugging, but you can`t do this in HTML.
When you have to touch the DOM, you should use Renderer2.

How to escape html encoding in detail template of 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)