I'd like to show / hide or change the icon of a toggle button and currently struggle getting this to work after changing to the current version.
I had no problems with older versions (2019 / 2021).
What I'm trying to achieve ist something like
setOptions({icon: "check"})
and (re)render()
I also tried to take the road via kendo.ui.icon(element....) and kendo.html.renderButton / renderIcon but so far to no avail.
Any hint would be greatly appreciated.
Kind regards
Frank
1 Answer, 1 is accepted

I'll try to answer my own question with a solution that I finally came up with. In case someone else needs it.
Mmimics the original behavior and procuces the same html. see kendo.html.button.js for reference.
Here less compact as it could be for better understanding and readability.
from within toggle():
// ...
toggle: function(e){
// 2023-06-24
let cClassAdd = e.checked ? "k-i-check" : "k-i-none",
cClassRem = e.checked ? "k-i-none" : "k-i-check";
if (kendo.version < "2023.1.425"){ // <-- our switchnig version. YMMV
e.target.find(".k-icon").removeClass(cClassRem).addClass(cClassAdd);
} else {
const
KBUTTONICON = "k-button-icon",
oButton = this,
oIconOptions = {icon: "", iconClass: cClassAdd};
let $IconEl = oButton.element.children("span.k-icon, span.k-svg-icon").first();
if ($IconEl.length < 1){ // or (!$IconEl[0])
// this should not happen unless someone ripped the span out
console.warn("Ooops... where is the icon?");
$IconEl = $(kendo.ui.icon(oIconOptions)).prependTo(oButton.element);
$IconEl.addClass(KBUTTONICON); // <-- here as given in the 'else'
} else {
// normal case
kendo.ui.icon($IconEl, oIconOptions);
}
}
// ...
}
Works from outside basicly the same way:. Just set
const oButton = $("#<ElementID>").data("kendoToggleButton");
Instead of the iconClass, You can use icon with the icon alias or the class name.
So these variants should work:
const oIconOptions = {icon: "", iconClass: "k-i-check"};
// or
const oIconOptions = {icon: "check", iconClass: ""};
// or
const oIconOptions = {icon: "k-i-check", iconClass: ""}; // <-- kendo.ui.icon() also looks for the classname
the not used option could be omitted
some additional information:
I now came across this document, that also has some valuable information:
https://docs.telerik.com/kendo-ui/styles-and-layout/sass-themes/font-icons-migration
You can read and/or set the default iconType. and adapt Your code accordingly Our version 2023.1.425 still defaults to "font" where as 2023.2.606 already uses "svg" by default.
console.log(kendo.defaults.iconType) // --> prints either "font" or "svg"
this can be set via
kendo.setDefaults('iconType', 'font');
// or
kendo.setDefaults('iconType', 'svg');
Hi, Frank,
Everything that you stated is correct.
One more approach that you can use to update the icon inside the `toggle` event is the following one:
toggle: function(e) {
let checked = e.checked,
iconElement;
// default icon is "save"
if(checked) {
// Find the current icon <span>
iconElement = e.sender.wrapper.find(".k-svg-i-save");
// Update the icon
kendo.ui.icon(iconElement, { icon: "pencil" });
} else {
// same as above
iconElement = e.sender.wrapper.find(".k-svg-i-pencil");
kendo.ui.icon(iconElement, { icon: "save" });
}
}
The kendo.ui.icon utility allows you to target the current icon `<span>` element and update it with a new one. There is no need to replace/append/remove the previous one.
Dojo
I prepared a small Dojo sample that you can examine:
https://dojo.telerik.com/@gdenchev/EfayukaY
Best Regards,
Georgi
Hi Georgi,
thanks for Your response! Good to know, I was on the right track.
I am actually doing the same as You recommended. The stuff around it is just fallback behavior for font icons and overly careful error prevention.
I have actually modified my post afterwards, but the portal said "saved for review" and did not update the content since.
The new approach is to check for iconType instead of version like
if (!kendo.defaults.iconType || kendo.defaults.iconType == "font"){
// --> font icons
} else {
// --> svg icons
}
We're currently migrating to the new version and unless we're sure everything works with the new version as expected, I'll have to be able to handle both variants.
Your code works fine if everything is as expected (and as a functional demo).
I like the e.sender.wrapper.find().. approach.
However, if for some reason the icon is not set as expected it will trigger an "Uncaught TypeError: i.element[0] is undefined" error.
So in real life, I'd probably cushion it a bit by checkiing the existance of the iconElement or even force the coming up icon to be the desired one.
This would be a bit more fail proof and works fine:
$("#button").kendoToggleButton({
toggle: function(e) {
let checked = e.checked,
iconElement;
// works if the correct icon is set:
// iconElement = e.sender.wrapper.find(checked ? ".k-svg-i-save": ".k-svg-i-pencil");
// but this finds the icon element regardless of the current icon
iconElement = e.sender.wrapper.find("span.k-svg-icon");
if (iconElement.length > 0){
kendo.ui.icon(iconElement, { icon: (checked ? "pencil" : "save") });
}
},
icon: "check" // <-- initialize with a "wrong" icon.
});
Have a great day!
Frank
Hi, Frank,
You're absolutely correct that it is better to have an additional check to ensure the item exists.
One more thing that I forgot to mention is that the `kendo.ui.icon` method will work for both SVG and Font icons.
With SVG it will replace the classes alongside the svg itself.
With Font icons, it will simply replace the classes on the element. So no matter which icon type you use, you can still utilize the method.
Dojo
https://dojo.telerik.com/@gdenchev/UpAWIhoc
Best Regards,
Georgi
Georgi,
thanks for the tip and the dojo.
I guessed that, but good to have it confirmed.
Have a great weekend!
Regards
Frank