This is a migrated thread and some comments may be shown as answers.

[Solved] ModifiedAppointment Looses Resources with AdvancedForm template

5 Answers 246 Views
Scheduler
This is a migrated thread and some comments may be shown as answers.
Egor
Top achievements
Rank 1
Egor asked on 27 Jul 2009, 10:20 AM

Hello,
 Im finding myself in a dead-end can't understand the issue origin. I explain gradually and post my code blocks if you ask me to.
Using RadScheduler and a new Advanced Form edit template in it for inserting and editing of my appointments, following exactly the pattern as your demo shows (LINK).

My Resources are 3:
- Services    (let's say its the Room from your example)  presented as ResourceControl.ascx (RadComboBox with entries)
- Operators (it's Alex, bob, charly that are able to solve services) as ResourceControl.ascx (another RadComboBox)
- Users ( Only Radscheduler has this one, i don't put this one into AdvancedForm.ascx) i only need this on Session level (login etc)

Mainly it's the Services-Operator couples that defines appointments.

Before describe My issue: i have DayView grouped by Services (like rooms in your case) and once inserted the appointment the drag-n-drop edit is only possible for start/end (vertical only) you can't drag it on another service.

so all i do is controll on Appointment_Update event

        if ((e.Appointment.Resources.GetResourceByType("Service") as Resource).Key.ToString() != (e.ModifiedAppointment.Resources.GetResourceByType("Service") as Resource).Key.ToString() ) 
            e.Cancel = true

this works perfectly.
If i control the resources there're 3 on Appointment and 3 on ModifiedAppointment (Service,Operator and User respectively).
Notice doing so the AdvancedForm is of course not shown

But once the thing Goes on AdvancedForm the resources are LOST !

example: I open already inserted appointment and modify let's say Subject and click Update, if i debug the AdvancedForm.ascx.cs (i put the Update_Button_Click Event to control some things) during that, i see the Appointment object (passed from scheduler to here has it's resources and there're all 3 of them during Update_button_click. After that it goes till MainPage.aspx where scheduler is, and of course till Appointment_Update event. When it goes to IF sentence i wrote before the NullReference happens :

ModifiedAppointment.Resources.GetResourceByType("Service") = null     !!!

if i debug this , i see the original Appointment still has 3 resources (Service, Operator, User)
BUT then modifiedAppointment has ONLY 1 (User)

It's as the Binding inside AdvancedForm the Two of my resources (Service and Operator) they're being sucked away by AdvancedForm or being forgot to add inside ModifiedApointment or else ... 

i debugged deeply inside all events of AdvancedForm.ascx.cs and haven't found any remove or loss of these resources, but as soon as the code goes to main page to scheduler events , the modifiedAppointment has 2 (binded) resources lost.

I'm in jeopardy, please help me  >_<

5 Answers, 1 is accepted

Sort by
0
Egor
Top achievements
Rank 1
answered on 27 Jul 2009, 04:42 PM
i did investigate more inside this troublesome situation and i definitely worked out that the great possibility is inside the mechanism of adding resources to Advanced Form, or passing them OUT to modifiedAppointment property inside the AppointmentUpdate Event.

I did (for example) removed one of 2 resources i've been using inside my AdvancedForm (Service and Operation) - i removed Service,
After that, inside the scheduler_appointmentUpdate event ModifiedAppointment was missing 1 Resource Only (Operator, the one is still binded throug AdvancedForm, but now there's service Resource tho).
Before both Operator and Service were binded inside AdvancedForm as result i had the ModifiedAppointment missed 2 of my total resources (having only 1 "user" still there, 'cuz i didn't binded it inside AdvancedForm).

 I scrolled the AdvancedForm.js   ,  as i don't want to lay my hands on it ('cuz of complexity of advancedForm) , and i found some things that seem to me strange.

    _saveResources : function (apt) 
    { 
        var template = this
        var schedulerResources = this._scheduler.get_resources(); 
 
        this._scheduler.get_resourceTypes().forEach(function(resourceType) { 
            var resourceTypeName = resourceType.get_name(); 
            var baseName = template._templateId + "_Res" + resourceTypeName; 
            var resourcesOfThisType = schedulerResources.getResourcesByType(resourceTypeName); 
 
            if (resourceType.get_allowMultipleValues()) 
            { 
                var checkBoxes = $(String.format("input[id*='{0}']", baseName), this._formElement); 
 
                if (checkBoxes.length > 0) 
                    apt.get_resources().removeResourcesByType(resourceTypeName); 
 
                for (var i = 0; i < checkBoxes.length; i++) 
                { 
                    if (checkBoxes[i].checked && resourcesOfThisType.get_count() >= i) 
                        apt.get_resources().add(resourcesOfThisType.getResource(i)); 
                }; 
            } 
            else 
            {
                var dropDown = $find(baseName); 
                if (!dropDown) 
                    return
 
                apt.get_resources().removeResourcesByType(resourceTypeName); 
 
                if (dropDown.get_selectedIndex() == 0) 
                    return
 
                var selectedValue = dropDown.get_selectedItem().get_value(); 
                var newResource = schedulerResources.findAll(function(res) { 
                    return res.get_type() == resourceTypeName && 
                           res._getInternalKey() == selectedValue; 
                }).getResource(0) || null
 
                if (newResource) 
                    apt.get_resources().add(newResource); 
            } 
        }); 
    }, 


the part of it in ELSE case where it operates on  Single-choice Resource (RadComboBox) he does really REMOVES the resource firstly, and then controls if there's a case to add it properly.

Is my whole problem origin is in someway linked to the fact of bad binding or negligence in passing the values properly, i still cant find the bug.

thanks.


0
Peter
Telerik team
answered on 30 Jul 2009, 08:53 AM
Hi Egor,

I am not sure why you experience this problem, so I have decided to send you a sample project using this kb article as a base and extending it to add one more resource type - Operator. Here are the changes to the code I have made to achieve this:

AdvancedForm.ascx
<%-- RESOURCE CONTROLS --%> 
                        <ul class="rsResourceControls">  
                            <li> 
                                <scheduler:ResourceControl  
                                    runat="server" ID="ResourceControl1" 
                                    Type="Room" 
                                    Label="Room:" Value='<%# Bind("Room") %>' 
                                    Skin='<%# Owner.Skin %>' /> 
                            </li> 
                            <li> 
                                <scheduler:ResourceControl  
                                    runat="server" ID="ResourceControl3" 
                                    Type="Operator" 
                                    Label="Operator:" Value='<%# Bind("Operator") %>' 
                                    Skin='<%# Owner.Skin %>' /> 
                            </li> 
                            <li> 
                                <scheduler:MultipleValuesResourceControl  
                                    runat="server" ID="ResourceControl2" 
                                    Type="User" Label="User: " Value='<%# Bind("User") %>' /> 
                            </li> 

AdvancedForm.ascx.cs
[Bindable(BindableSupport.Yes, BindingDirection.TwoWay)]  
        public object OperatorID  
        {  
            get 
            {  
                return ResourceControl3.Value;  
            }  
 
            set 
            {  
                ResourceControl3.Value = value;  
            }  
        } 

DefaultCS.aspx
<AdvancedEditTemplate> 
                <scheduler:AdvancedForm runat="server" ID="AdvancedEditForm1" Mode="Edit" Subject='<%# Bind("Subject") %>' 
                    Start='<%# Bind("Start") %>' End='<%# Bind("End") %>' Description='<%# Bind("Description") %>' RecurrenceRuleText='<%# Bind("RecurrenceRule") %>' 
                    UserID='<%# Bind("User") %>' RoomID='<%# Bind("Room") %>'  OperatorID='<%# Bind("Operator") %>' /> 
            </AdvancedEditTemplate> 
            <AdvancedInsertTemplate> 
                <scheduler:AdvancedForm runat="server" ID="AdvancedInsertForm1" Mode="Insert" Subject='<%# Bind("Subject") %>' 
                    Start='<%# Bind("Start") %>' End='<%# Bind("End") %>' Description='<%# Bind("Description") %>' RecurrenceRuleText='<%# Bind("RecurrenceRule") %>' 
                    UserID='<%# Bind("User") %>' RoomID='<%# Bind("Room") %>' OperatorID='<%# Bind("Operator") %>' /> 
            </AdvancedInsertTemplate> 

DefaultCS.aspx.cs
 protected void RadScheduler1_DataBound(object sender, EventArgs e)  
    {  
        RadScheduler1.ResourceTypes.FindByName("User").AllowMultipleValues = true;  
        RadScheduler1.ResourceTypes.FindByName("Operator").AllowMultipleValues = false;  
        RadScheduler1.ResourceTypes.FindByName("Room").AllowMultipleValues = false;  
    } 

Appointments_CustomTemplates.xml
 <Resources> 
    <Room> 
      <Key>1</Key> 
      <Text>Meeting room 101</Text> 
    </Room> 
    <Room> 
      <Key>2</Key> 
      <Text>Meeting room 201</Text> 
    </Room> 
    <Operator> 
      <Key>1</Key> 
      <Text>Operator A</Text> 
    </Operator> 
    <Operator> 
      <Key>2</Key> 
      <Text>Operator B</Text> 
    </Operator> 
    <User> 
      <Key>1</Key> 
      <Text>Alex</Text> 
    </User> 
    <User> 
      <Key>2</Key> 
      <Text>Bob</Text> 
    </User> 
    <User> 
      <Key>3</Key> 
      <Text>Charlie</Text> 
    </User> 
  </Resources> 

Note that the xml scheduler provider automatically takes care of additional resources or attributes added to the xml file it uses.

I hope this helps.

All the best,
Peter
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
Egor
Top achievements
Rank 1
answered on 30 Jul 2009, 10:22 AM
Hello Peter,

   thanks for reply, but this esample of yours doesn't quite figures out my problem,
on this page of DEMO: (http://demos.telerik.com/aspnet-ajax/scheduler/examples/advancedformtemplate/defaultcs.aspx)

i don't know if my problem applys on this case, but see yourself the situation:

 if you click near "meeting with customers" the first appointment (9.00am) in way to insert new appointment starting 9.00 also (or in range of the first appointment anyway), theoretically the Resource "Meeting Room 101" and "Charly" and "Bob" are already used in the first appointment.

WHY they're there still present as choice inside advancedForm for inserting NEW appointment?  aren't their ariety shall be 1 ? if a Room is already used for some kind of appointment, i can't use it for another one in the same time lapse. The same way Charly and Bob don't have double twins for being inside one appointment and another (at least i suppose they don't).


I tested the example project you've sent me, adding the AppointmentUpdate event to shceduler.
The e.ModifiedAppointment works correctly, it has the correct number of resources, and resources defers from the ones in e.Appointment if they were modified.
The way you bind the infomation inside your scheduler is the same way i do that. The same in AdvanceForm.ascx and the Bindable values for single controls. I followed the pattern like a blind man follows his dog.
The one difference is that i use SQL Database instead of XML. (may this be the cause of the mess up ?)

Another thing: do i actually need to write this as in your example (i did but nothing changes).
What's the purpose of this code-block inside databind ?
 protected void RadScheduler1_DataBound(object sender, EventArgs e)   
    {   
        RadScheduler1.ResourceTypes.FindByName("User").AllowMultipleValues = true;   
        RadScheduler1.ResourceTypes.FindByName("Operator").AllowMultipleValues = false;   
        RadScheduler1.ResourceTypes.FindByName("Room").AllowMultipleValues = false;   
    }  


Still in queue for a help reply if possible.
Best regards, Egor.

0
Peter
Telerik team
answered on 30 Jul 2009, 02:28 PM
Hi Egor,

Probably, you need functionality similar to this demo:
http://demos.telerik.com/aspnet-ajax/scheduler/examples/resourceavailability/defaultcs.aspx
Note, that this functionality is not provided out-of-the box and that we implement it using the RadScheduler's API. 

tthe data source, whether SQL, xml, or any other type for that matter, is of no significance when using the advanced templates.

Setting AllowMultipleValues in RadScheduler's DataBound event indicates which resource will support multiple values (checkbox list to select from) and which will be just a single value resource (dropdownlist). However, setting this property by itself is not sufficient. For multiple value resource you need to implement a provider:
http://www.telerik.com/help/aspnet-ajax/schedule_databindingimplementingaproviderthatsupportsmultivaluedresources.html
In the sample project, this is taken care of by the XmlSchedulerProvider. In additon to this you should use the MultipleValuesResourceControl in the AdvancedForm.




Kind regards,
Peter
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Check out the tips for optimizing your support resource searches.
0
Egor
Top achievements
Rank 1
answered on 30 Jul 2009, 03:41 PM
Hello Peter,

For AllowMultipleResourceValues is ok, i understood.

The Occupied Resource made Client-Side from RadScheduler API also is clear (originally my idea was to make it that way as in demo version you linked me).

First case, before the new AdvanceForm was introduced, i had the simple Inline insert/edit template with dropdowns for my resources, and guess what ... scheduler made all by itself not showing the resources already used. It was cool and functional, but i also need the recurrence rules for my appointments. And this ofc the AdvancedForm is needed for. Since passing all through the ResourceControls binds the problem i described at the beginning shows up.

Reading thoroughly the code from all the solution provided for AdvancedForm  many questions rised my attention.
for example:

part of ResourceControll.ascx.cs

    protected void Page_Load(object sender, EventArgs e) 
        { 
 
            if (ResourceValue.Items.Count == 0) 
            { 
                PopulateResources(); 
                MarkSelectedResource(); 
            } 
    } 
 
 
        private void PopulateResources() 
        { 
            foreach (Resource res in GetResources(Type)) 
            { 
                ResourceValue.Items.Add(new RadComboBoxItem(res.Text, SerializeResourceKey(res.Key))); 
            } 
        } 
 
 
        private void MarkSelectedResource() 
        { 
            ResourceValue.Items.Insert(0, new RadComboBoxItem("-", "NULL")); 
 
            Resource res = Appointment.Resources.GetResourceByType(Type); 
            if (res != null) 
            { 
                ResourceValue.SelectedValue = SerializeResourceKey(res.Key); 
            } 
        } 
 
 
        private IEnumerable<Resource> GetResources(string resType) 
        { 
            List<Resource> availableResources = new List<Resource>(); 
            IEnumerable<Resource> resources = Owner.Provider.GetResourcesByType(Owner, resType); 
 
            foreach (Resource res in resources) 
            { 
                if (IncludeResource(res)) 
                { 
                    availableResources.Add(res); 
                } 
            } 
 
            return availableResources; 
        } 
 
 
        private bool IncludeResource(Resource res) 
        { 
            return res.Available || ResourceIsInUse(res); 
        } 
 
 
        private bool ResourceIsInUse(Resource res) 
        { 
            foreach (Resource appRes in Appointment.Resources) 
            { 
                if (res == appRes) 
                { 
                    return true; 
                } 
            } 
 
            return false; 
        } 
 
it's the single Resource (Dropdown). The populating of this resource is the thing i think is strange.

1. it gets the all resources from Owner (radscheduler)     GetResources of the Type the ResourceControl is set.
2. controls for each resource in that list if it has to be added to the dropdown.
3. during the control:   if resource is available  OR  is in use ....   WHY?  i think it SHOULD be added if it is Available AND is NOT in use elswhere.
4. there's more ... ResourceIsInUse controls if the resource is in use INSIDE this same Appointment ...?
why inside THIS appointment , and not inside all the apointments of scheduler in range of this inserted/edited appointment ?

BUT the 4) is useless in my opinion, cus the res.Available   in   3) is always true and the 4) is never controlled. There's never once inside the AdvanceForm or Scheduler who sets the one particular resource being NOT available.

That's the all observations i've made to this point.
Thanks again for all the time used upon my issues.

Best regards, Egor.
Tags
Scheduler
Asked by
Egor
Top achievements
Rank 1
Answers by
Egor
Top achievements
Rank 1
Peter
Telerik team
Share this question
or