views:

741

answers:

3

Say I have two script controls and one control has the other as a child control:

ParentControl : ScriptControl
{
   ChildControl childControl;
}

The script for the Child Control:

ChildControl = function(element) 
{
  ChildControl.initializeBase(this, [element]);
}

ChildControl.prototype =
{
    callMethod: function()
    {
      return 'hi';
    },

    initialize: function() 
    {
      ChildControl.callBaseMethod(this, 'initialize');
    },

    dispose: function() 
    {
      ChildControl.callBaseMethod(this, 'dispose');
    }
}

And on script side I want to call a method on the child control:

ParentControl.prototype =
{
    initialize: function() 
    {
      this._childControl = $get(this._childControlID);
      this._childControl.CallMethod();

      ParentControl.callBaseMethod(this, 'initialize');
    },

    dispose: function() 
    {
      ParentControl.callBaseMethod(this, 'dispose');
    }
}

Problem is, everytime I try this is says this method isn't found or supported. Shouldn't all methods on the ChildControl be accessible by the ParentControl?

Is there some way I have to make the method public so that the ParentControl can see it?

Update Would it be possible to "type" the this._childControl?

Here's the reason I ask... When I use Watch, the system knows what the ChildControl class is, and I can call methods off the class itself, however, I can't call the same methods off the this._childControl object. You would think that if the class design (?) in memory recognizes the method existing, and object instantiated from that class would too.

+1  A: 

The problem is the "this." This, in javaScript, refers to the DOM object. You need to do something similar to what happens when you use Function.createDelegate, which is required when using $addHandler (which I know you're not using, just giving context).

Robert C. Barth
+1  A: 

On the client, you're using a field of your parent control object called _childControlID by passing it into $get. There's a few problems with this:

  1. How did _childControlID get set? I would guess by adding it as a property in the parent control's descriptor on the server, but you don't show that code and you don't show a property on the client-side parent control class.
  2. $get returns element references--not controls. So even if _childControlID was set to a valid element ID, that element won't have a method called CallMethod. If the client-side child control class did initialize before the parent control, the element will have a field called "control" that you can use to access the script control that "attached" itself to the element. This only works if the child control initialized before the parent control, of course.
Jason Diamond
Next problem is removing the handler since it looks like the child is being removed before the part, and therefore (I'm guessing) the child's control object no longer exsits.
Programmin Tool
A: 

You have a couple options.

  1. You can find your child script control by using $find(). But you run into the risk of your parent control being initialized before the child control.

    this._childControl = $find(this._childControlID);
    this._childControl.CallMethod();
    
  2. You can register a property in your control descriptor on the server using AddComponentProperty(). This will make sure that all child controls are initialized before the parent control is initialized.

    public class CustomControl : WebControl, IScriptControl
    {
         public ScriptControl ChildControl { get; set; }
    
    
    
     public IEnumerable<ScriptDescriptor> GetScriptDescriptors()
     {
         var descriptor = new ScriptControlDescriptor("Namespace.MyCustomControl", this.ClientID);
         descriptor.AddComponentProperty("childControl", ChildControl.ClientID);
    
    
         return new ScriptDescriptor[] { descriptor };
     }
    
    
     public IEnumerable<ScriptReference> GetScriptReferences()
     {
         var reference = new ScriptReference
                         {
                             Assembly = this.GetType().Assembly.FullName,
                             Name = "MyCustomControl.js"
                         };
    
    
         return new ScriptReference[] { reference };
     }
    
    }

Then as long as you create a client side property "childControl" it will automatically be initialized and ready for use within the parent controls init() method.

Wallace Breza