Problem creating designer for custom widget
I am having a problem creating my designer with multiple properties. I followed the Hello World tutorial and was able to get that working properly but now I am trying to add page selector and title properties. I keep getting a javascript error "b is undefined" and the edit screen is completely blank. Can't seem to figure out why this is happening. Below is my code for my designer.
I have 3 properties in my widget. Message, ButtonTitle, PageID
Designer.js
Type.registerNamespace("SitefinityWebApp.Widgets.EmptyLeg.Designer");
SitefinityWebApp.Widgets.EmptyLeg.Designer.EmptyLegListDesigner = function (element)
this._Message = null;
this._ButtonTitle = null;
this._PageSelector = null;
SitefinityWebApp.Widgets.EmptyLeg.Designer.EmptyLegListDesigner.initializeBase(this, [element]);
SitefinityWebApp.Widgets.EmptyLeg.Designer.EmptyLegListDesigner.prototype =
/* --------------------------------- set up and tear down --------------------------------- */
initialize: function ()
/* Here you can attach to events or do other initialization */
SitefinityWebApp.Widgets.EmptyLeg.Designer.EmptyLegListDesigner.callBaseMethod(this, 'initialize');
,
dispose: function ()
/* this is the place to unbind/dispose the event handlers created in the initialize method */
SitefinityWebApp.Widgets.EmptyLeg.Designer.EmptyLegListDesigner.callBaseMethod(this, 'dispose');
,
/* --------------------------------- public methods ---------------------------------- */
/* Called when the designer window gets opened and here is place to "bind" your designer to the control properties */
refreshUI: function ()
var controlData = this._propertyEditor.get_control(); /* JavaScript clone of your control - all the control properties will be properties of the controlData too */
/* RefreshUI Message */
jQuery(this.get_Message()).val(controlData.Message);
jQuery(this.get_Button()).val(controlData.ButtonTitle);
var p = this.get_PageSelector();
var pageid = controlData.SelectedPageID;
if (pageid) p.set_value(pageid);
,
/* Called when the "Save" button is clicked. Here you can transfer the settings from the designer to the control */
applyChanges: function ()
var controlData = this._propertyEditor.get_control();
controlData.Message = jQuery(this.get_Message()).val();
controlData.PageID = this.get_PageSelector().get_value();
controlData.ButtonTitle = jQuery(this.get_Button()).val();
,
/* --------------------------------- event handlers ---------------------------------- */
/* --------------------------------- private methods --------------------------------- */
findElement: function (id)
var result = jQuery(this.get_element()).find("#" + id).get(0);
return result;
,
/* --------------------------------- properties -------------------------------------- */
/* Message properties */
get_Message: function () return this._Message; ,
get_Button: function () return this._ButtonTitle; ,
get_PageSelector: function () return this._PageSelector; ,
set_Message: function (value) this._Message = value; ,
set_Button: function (value) this._ButtonTitle = value; ,
set_PageSelector: function (value) this._PageSelector = value;
SitefinityWebApp.Widgets.EmptyLeg.Designer.EmptyLegListDesigner.registerClass('SitefinityWebApp.Widgets.EmptyLeg.Designer.EmptyLegListDesigner', Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesignerBase);
#region Properties
/// <
summary
>
/// Gets the layout template path
/// </
summary
>
public override string LayoutTemplatePath
get
return EmptyLegListDesigner.layoutTemplatePath;
/// <
summary
>
/// Gets the layout template name
/// </
summary
>
protected override string LayoutTemplateName
get
return String.Empty;
protected override HtmlTextWriterTag TagKey
get
return HtmlTextWriterTag.Div;
#endregion
#region Control references
/// <
summary
>
/// Gets the control that is bound to the Message property
/// </
summary
>
protected virtual TextBox Message
get return this.Container.GetControl<
TextBox
>("Message", true);
protected virtual TextBox ButtonTitle
get return this.Container.GetControl<
TextBox
>("ButtonTitle", true);
protected PageField PageSelector
get return Container.GetControl<
PageField
>("PageSelector", true);
/// <
summary
>
/// Gets or sets the ID of the selected page.
/// </
summary
>
/// <
value
>
/// The selected page ID.
/// </
value
>
public Guid SelectedPageID get; set;
#endregion
#region Methods
protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container)
// Place your initialization logic here
this.PageSelector.RootNodeID = Telerik.Sitefinity.Abstractions.SiteInitializer.FrontendRootNodeId;
#endregion
#region IScriptControl implementation
/// <
summary
>
/// Gets a collection of script descriptors that represent ECMAScript (JavaScript) client components.
/// </
summary
>
public override System.Collections.Generic.IEnumerable<
System.Web.UI.ScriptDescriptor
> GetScriptDescriptors()
var scriptDescriptors = new List<
ScriptDescriptor
>(base.GetScriptDescriptors());
var descriptor = (ScriptControlDescriptor)scriptDescriptors.Last();
descriptor.AddElementProperty("Message", this.Message.ClientID);
descriptor.AddElementProperty("ButtonTitle", this.ButtonTitle.ClientID);
descriptor.AddElementProperty("PageSelector", this.PageSelector.ClientID);
return scriptDescriptors;
/// <
summary
>
/// Gets a collection of ScriptReference objects that define script resources that the control requires.
/// </
summary
>
public override System.Collections.Generic.IEnumerable<
System.Web.UI.ScriptReference
> GetScriptReferences()
var scripts = new List<
ScriptReference
>(base.GetScriptReferences());
scripts.Add(new ScriptReference(EmptyLegListDesigner.scriptReference));
return scripts;
#endregion
#region Private members & constants
public static readonly string layoutTemplatePath = "~/Widgets/EmptyLeg/Designer/EmptyLegListDesigner.ascx";
public const string scriptReference = "~/Widgets/EmptyLeg/Designer/EmptyLegListDesigner.js";
#endregion
<%@ Register Assembly="Telerik.Sitefinity" TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI" %>
<%@ Register Assembly="Telerik.Sitefinity" TagPrefix="sitefinity" Namespace="Telerik.Sitefinity.Web.UI" %>
<%@ Register Assembly="Telerik.Sitefinity" TagPrefix="sfFields" Namespace="Telerik.Sitefinity.Web.UI.Fields" %>
<
sitefinity:ResourceLinks
ID
=
"resourcesLinks"
runat
=
"server"
>
<
sitefinity:ResourceFile
Name
=
"Styles/Ajax.css"
/>
</
sitefinity:ResourceLinks
>
<
sitefinity:FormManager
ID
=
"formManager"
runat
=
"server"
/>
<
div
class
=
"sfContentViews sfSingleContentView"
style
=
"max-height: 600px; overflow: auto; "
>
<
ol
>
<
li
class
=
"sfFormCtrl"
>
<
asp:Label
runat
=
"server"
AssociatedControlID
=
"Message"
CssClass
=
"sfTxtLbl"
>Message</
asp:Label
>
<
asp:TextBox
ID
=
"Message"
runat
=
"server"
CssClass
=
"sfTxt"
ClientIDMode
=
"Static"
/>
<
div
class
=
"sfExample"
>The label's message</
div
>
</
li
>
<
li
class
=
"sfFormCtrl"
>
<
asp:Label
ID
=
"lblTitle"
runat
=
"server"
AssociatedControlID
=
"ButtonTitle"
CssClass
=
"sfTxtLbl"
>Button Title</
asp:Label
>
<
asp:TextBox
ID
=
"ButtonTitle"
runat
=
"server"
CssClass
=
"sfTxt"
ClientIDMode
=
"Static"
/>
<
div
class
=
"sfExample"
>The title shown on the button</
div
>
</
li
>
<
li
class
=
"sfFormCtrl"
>
<
asp:Label
ID
=
"Label1"
runat
=
"server"
AssociatedControlID
=
"PageSelector"
CssClass
=
"sfTxtLbl"
>Page</
asp:Label
>
<
sfFields:PageField
ID
=
"PageSelector"
runat
=
"server"
WebServiceUrl
=
"~/Sitefinity/Services/Pages/PagesService.svc/"
DisplayMode
=
"Write"
ClientIDMode
=
"Static"
/>
<
div
class
=
"sfExample"
>The page user is redirected to</
div
>
</
li
>
</
ol
>
</
div
>
this usually happens if the designer script isn't loaded properly or if the namespaces in it don't match the control. can you verify that your designer js file is loaded with a tool like firebug?
Also, I highly recommend you now use Sitefinity Thunder for this, as it has an item template to build a designer for an existing widget that will let you assign a Page Selector to a Guid property automatically.
hope this is helpful!
I feel your pain here. The javascript error messages that the template designers give are very hard to understand because the variable names are not meaningful. I took the code you provided and slapped it on one of my user controls on my project to see if I could help you. Lo and behold, I was able to reproduce the error with your code.
To solve your error you will need to change the following in your Designer.cs
descriptor.AddElementProperty("Message", this.Message.ClientID);
descriptor.AddElementProperty("ButtonTitle", this.ButtonTitle.ClientID);
descriptor.AddElementProperty("PageSelector", this.PageSelector.ClientID);
descriptor.AddComponentProperty("Message", this.Message.ClientID);
descriptor.AddComponentProperty("Title", this.Title.ClientID);
descriptor.AddComponentProperty("PageSelector", this.PageSelector.ClientID);
Sorry, I figured it out. thanks, I got it working.
I've never experienced the bug you are getting now and I do not know where to begin. I don't ever use Thunder so I am not sure I can help you anymore. Maybe SelAromDotNet can give you some additional help. Good luck!
Not sure if you will see this, but is there any chance you can elaborate on your fix?
I am experiencing the exact same issue and cannot seem to find what I am missing. As soon as I try to add another descriptor of any sort to the GetScriptDescriptors() method it causes my designer widget to be a blank window.
Any help would be greatly appreciated!!
Hi Christopher,
Looking through Daniel's code the problem is that all Button references should be with the ID of the control by convention. See the following:
get_Button: function () return this._ButtonTitle; ,
<
asp:TextBox
ID
=
"ButtonTitle"
runat
=
"server"
CssClass
=
"sfTxt"
ClientIDMode
=
"Static"
/>
get_ButtonTitle: function () return this._ButtonTitle; ,
That did the trick.
Thanks all for the help!
In response to Brett Whittington's first post, I would like to say first of all thank you. You gave an answer, and although it didn't help me directly, it showed me how to debug. I have a problem though. I was doing the same thing that D.Tharp was doing, which was adding fields to a widget, and I ran into some crazy error when I clicked edit. It looked like I added all of the changes that would make the new fields work, but since it didn't, I decided to do what Brett suggested, which was comment out all of the changes, then add them one by one.
The problem is, I commented everything out, and it still doesn't work! I still get some crazy 500 internal server error. Why doesn't sitefinity go back to the way it was? How is it saving things that when I build, and then revert, they are still there (You know what I mean). I keep cleaning and rebuilding, and I still get this error. Do I have to restart my computer?
Hello Jeremy,
It is really strange. Most probably there is some custom logic that you have not commented out and this causing the issue. It is really hard to say what is the exact issue since the error message you are getting (Internal server error 500) does not provide sufficient information to say what exactly is causing the issue.
Can you please also inspect the browser's console to check if there are any errors logged there which may provide more details about the issue?
What I can also suggest is to take a look at the following resources for more details about creating widget designers:
Create a simple widget designer
Thunder: Create widget designers
Creating a Custom Widget Designer using Sitefinity and Sitefinity Thunder Part 1
Creating a Custom Widget Designer Using Sitefinity and Sitefinity Thunder Part 2
Regards,
Sabrie Nedzhip
Telerik