Welcome, Guest. Please login or register.
Did you miss your activation email?
Oct. 11, 2008, 03:33:10 PM
47672 Posts in 10455 Topics by 5339 Members
Latest Member: phamlehoaian
News: New to PRADO? The PRADO blog tutorial is a good start point.
 
The PRADO Community » Prado v3.x » General Discussion » [SOLVED] Help with custom control: TEffectPanel « previous next »
Pages: [1] Print
Author Topic: [SOLVED] Help with custom control: TEffectPanel  (Read 962 times)
mikl
PRADO v3.x Developer
Platinum Member
*****

Karma: 51
Offline Offline

Posts: 733



View Profile
« on: Nov. 07, 2006, 05:02:41 PM »

Sorry, if this post is really long. I just tried to give every information i've already gathered. So please only read this, if you think you can give a helping hand or some tipps. I try to keep it as concise as possible.

What is it?
I'd like to create a custom component to ease the handling of dynamically appearing or disappearing panels using scriptaculous Effects. I've already created some easy controls and understand the basics. In this case i already understand what needs to be done and even have put together a working example. But i think i need some hints on where the bits and pieces will go to transform this into a new component.

Think for example of a list of Radiobuttons:

  O Option 1
  O Option 2
  O Other 

When Other is checked, a panel should appear below with some extra fields and validators. The panel should disappear when option 1 or 2 is checked. Also the validators inside must be enabled/disabled accordingly.

How can this be done? - The hard way
The code below already does exactly what i want. Including a fallback mechanism if js is disabled:

Classicpanel.page
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" >
<com:THead Title="EffectsPanel - The hard way" />
<com:TClientScript PradoScripts="effects" />
<body>
<com:TForm>

    <com:TRadioButton ID="R1" GroupName="A" Text="Option A" Checked="true"
        Attributes.onClick=<%= "if ( $('{$this->EP->ClientID}').style.display=='')
        new Effect.SlideUp('{$this->EP->ClientID}', {duration: .5, queue: 'end'});"%> /><br />
    <com:TRadioButton ID="R2" GroupName="A" Text="Option B"
        Attributes.onClick=<%= "if ( $('{$this->EP->ClientID}').style.display=='')
        new Effect.SlideUp('{$this->EP->ClientID}', {duration: .5, queue: 'end'});"%> /><br />
    <com:TRadioButton ID="R3" GroupName="A" Text="Other Option"
        Attributes.onClick=<%= "if ( $('{$this->EP->ClientID}').style.display=='none')
          new Effect.SlideDown('{$this->EP->ClientID}',{duration: .5, queue: 'end'});"%> /><br />

    <com:TPanel ID="EP" Attributes.Style="display:none; border: 1px solid black" >
    <div>
      <com:TTextBox ID="Option" /><br />
      <com:TRequiredFieldValidator ID="V1" Text="Please enter something<br />" EnableClientScript="true"
          ControlToValidate="Option" Display="Dynamic" OnValidate="Page.EPOnValidate"
          ClientSide.OnValidate=<%=
          "sender.isValid=true;sender.enabled = $('{$this->R3->ClientID}').checked ? true:false"%> />
      <com:TLabel Text="Other Option" ForControl="Option" /><br />

      <com:TTextBox ID="Features" /><br />
      <com:TRequiredFieldValidator ID="V2" Text="Please enter something<br />" EnableClientScript="true"
          ControlToValidate="Features" Display="Dynamic" OnValidate="Page.EPOnValidate"
          ClientSide.OnValidate=<%=
          "sender.isValid=true;sender.enabled = $('{$this->R3->ClientID}').checked ? true:false;"%> />
      <com:TLabel Text="Features" ForControl="Features" />
    </div>
    </com:TPanel>
    <com:TButton ID="S" Text="Submit" CausesValidation="true" OnClick="process" />
    <p><com:TLiteral ID="Result" /></p>
</com:TForm>
</body>
</html>

Classicpanel.php
Code:
class Classicpanel extends TPage {

    public function onLoad ($param) {
        // display panel if R3 is checked
        $this->EP->setSubProperty('Attributes.Style', "display:". ($this->R3->Checked ? '':'none') );
    }

    public function onPreRender($param) {
        // Re-enable Validators in case EPOnValidate has disabled them (to prevent validation)
        // otherwhise client scripts will not be included for hidden panel
        $this->V1->Enabled = true;
        $this->V2->Enabled = true;
    }

    public function EPOnValidate ($sender, $param) {
        // Disable validators if panel is not visible (fallback if js is not available)
        $sender->Enabled = $this->R3->Checked;
    }

    public function process($sender,$param) {
        $this->Result->Text = $this->IsValid ? 'OK!' : 'Not OK!';
    }
}

You see there are many identical parts in the page template. The situation gets even worse if you have more controls inside the panel.

What should the new component look like?
Now heres what i'd like to have: A new componenet TEffectPanel where i can define an effect for appearing/hiding and which controls trigger these Effect. The triggering controls could be a checkbox or a radio button.

So the above example would look like this.
Code:
<com:TForm>

    <com:TRadioButton ID="R1" GroupName="A" Text="Option A" Checked="true" /><br />
    <com:TRadioButton ID="R2" GroupName="A" Text="Option B" /><br />
    <com:TRadioButton ID="R3" GroupName="A" Text="Other Option" /><br />

    <com:TEffectPanel ID="EP" Attributes.Style="border: 1px solid black"
        DefaultState="On"
        AppearEffect="Effect.SlideDown"
        AppearEffectOptions="{duration:.5,queue:'end'}"
        HideEffect="Effect.SlideUp"
        HideEffectOptions="{duration:.5,queue:'end'}"
        AppearControls="R3"
        HideControls="R1,R2">
    <div>
      <com:TTextBox ID="Option" /><br />
      <com:TRequiredFieldValidator ID="V1" Text="Please enter something<br />" EnableClientScript="true"
          ControlToValidate="Option" Display="Dynamic" />
      <com:TLabel Text="Other Option" ForControl="Option" /><br />

      <com:TTextBox ID="Features" /><br />
      <com:TRequiredFieldValidator ID="V2" Text="Please enter something<br />" EnableClientScript="true"
          ControlToValidate="Features" Display="Dynamic" />
      <com:TLabel Text="Features" ForControl="Features" />
    </div>
    </com:TEffectPanel>
    <com:TButton ID="S" Text="Submit" CausesValidation="true" OnClick="process" />
    <p><com:TLiteral ID="Result" /></p>
</com:TForm>

The new Component would have these Properties:

DefaultState - Should the panel be in state on or off by default?
AppearEffect - Effect to use for the appearing panel
AppearEffectOptions - Options for the appear effect
HideEffect - Effect to use for hiding
HideEffectOptions - Options for the hiding effect
AppearControls - Name(s) of controls that trigger appearing
HideControls - Name(s) of controls that trigger hiding

What needs to be done?
I think i know how i could build this component but i feel like i would take large detours. So maybe someone could give some hints on how to get what i want.

Basically it comes down to this tasks (also see upper code for a static implementation):

  • The appear effects have to be set as onClick events for the AppearControls including some check if the control is already visible to prevent "doubling" of the appearing animation
  • Same for the hide effect and HideControls
  • Every validator inside the TEffectPanel needs some js attached to enable/disable validation according to the visibility state of the panel
  • Every validator inside the panel needs to call a function at the OnValidate event to enable/disable validation on serverside to ensure fallback functionality
  • In the onLoad event of the Page we need to check if one of the AppearControls is checked to set the visibility of the panel accordingly(fallback)
  • In the onPreRender event of the Page every validator inside the panel is re-enabled to assure js inclusion even if the panel was invisible on submission

That's pretty much it Smiley

So - what's the problem?
I don't know (from a component perspective)
  • what's the best way to get all validators inside a panel (and all sub-panels)
  • how to attach some custom code to the page's OnLoad/OnPreRender event, the OnClick event of the AppearControls/HideControls and the OnValidate events of the validators inside the panel without breaking up existing stuff a user might have configured
  • how to make sure that effects.js is included

I feel like everything is right there before my eyes but the above points are still bothering me. I also don't know, if the component is already enough "general" to be useful in other cases. So thanks for every hint.
« Last Edit: Nov. 12, 2006, 10:48:26 PM by mikl » Logged
mikl
PRADO v3.x Developer
Platinum Member
*****

Karma: 51
Offline Offline

Posts: 733



View Profile
« Reply #1 on: Nov. 12, 2006, 10:48:06 PM »

I've solved the above problems. My custom component is working - Yippie  Cheesy

It's only a quick hack without much error checking but already works great when using RadioButtons and CheckBoxes as Apper/HideControls. If anyone is interested in this component i'll post it to the Component Repository in this forum. Otherwhise i'll give it some more tweaks and post it later.

Ideas on how to improve its usability are still welcome!

Thanks anyway, this forum is a real treasure when you try to find your way through PRADO.
Logged
eirikhm
Platinum Member
****

Karma: 27
Offline Offline

Posts: 778



View Profile WWW
« Reply #2 on: Nov. 12, 2006, 11:02:18 PM »

Cool. I'd like to take a look at it when I get the time:)
Logged

marcosanobre
Senior Member
***

Karma: 1
Offline Offline

Posts: 183


View Profile
« Reply #3 on: Aug. 19, 2008, 04:14:26 AM »

Very, very great component.

How can I 'close' the panel in code ?

I tryed : $this->magicPanel->setSubProperty('Attributes.Style', "display:none;" );
but isn't runs very well.

Any clue ?

TIA:

MN.
Logged
Pages: [1] Print 
« previous next »
Jump to: