Gantt Filtering with CustomAdapter

HI!

When using  DataAdaptor filtering function

because of the the initial filtering (ParentId equal null) only top record visible the Chart.


if we disable the filtering function-> all record visibled, but the column filtering not working:


What is the best solution so that all items are visible and the filtering works?



5 Replies

AG Ajithkumar Gopalakrishnan Syncfusion Team May 26, 2023 12:36 PM UTC

Hi Szoke,

Greetings from Syncfusion Support.

We are able to replicate the problem. In order to overcome this, we recommend using a custom adapter and a FilterTemplate to achieve the desired outcome. In your case, since the column type is string, the filter template can be utilized. We have provided a sample filter with child records attached for your reference.

<SfGantt …..>

    <GanttColumns>

        <GanttColumn Field="TaskID" HeaderText="Task ID" IsPrimaryKey="true" Width="80" TextAlign="TextAlign.Right"></TreeGridColumn>

        <GanttColumn Field="TaskName" HeaderText="Task Name" Width="145">

             <FilterTemplate>   

                <SfDropDownList Placeholder="TaskName" ID="TaskName" @bind-Value="@((context as PredicateModel<string?>).Value)" TItem="SelfReferenceData" TValue="string?" DataSource="@(TreeData)">    

                    <DropDownListFieldSettings Value="TaskName" Text="TaskName"></DropDownListFieldSettings>       

                    </SfDropDownList>     

                    </FilterTemplate>

        </GanttColumn>

….

</SfGantt>

   

@code {

    public static List<SelfReferenceData> GanttData { get; set; }

    public static List<SelfReferenceData> FilteredData = new List<SelfReferenceData>();

    public static int? filterCount;

    public double ID { get; set; } = 10;

    protected override void OnInitialized()

    {

        // SelfReferenceData data = new SelfReferenceData();

        GanttData = GetTree().ToList();

    }

 

// Implementing custom adaptor by extending the DataAdaptor class

    public class CustomAdaptor : DataAdaptor

    {

        // Performs data Read operation

        public override object Read(DataManagerRequest dm, string key = null)

        {

            IEnumerable<SelfReferenceData> DataSource = GanttData;

            if (dm.Search != null && dm.Search.Count > 0)

            {

                // Searching

                DataSource = DataOperations.PerformSearching(DataSource, dm.Search);

            }

            if (dm.Sorted != null && dm.Sorted.Count > 0)

            {

                // Sorting

                DataSource = DataOperations.PerformSorting(DataSource, dm.Sorted);

            }

            if (dm.Where != null && dm.Where.Count > 0)

            {

                // Filtering

                if (dm.Where[0].Field != null && dm.Where[0].Field == "ParentID")

                {

 

                }

                else

                {

                    DataSource = DataOperations.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);

                }

            }

            int count = DataSource.Cast<SelfReferenceData>().Count();

            if (dm.Skip != 0)

            {

                //Paging

                DataSource = DataOperations.PerformSkip(DataSource, dm.Skip);

            }

            if (dm.Take != 0)

            {

                DataSource = DataOperations.PerformTake(DataSource, dm.Take);

            }

            if (dm.Where != null && dm.Where.Count > 0)

            {

                if (dm.Where[0].Field == null)

                {

                    FilteredData.Clear();

 

                    filterCount = 0;

                    //for filterhierarchy mode as "parent"(default mode), we need to return the parent record of the filtered record along with the actual filtered record

                    //calling filterhierarchydata to collect the parent data of filtered data by passing filtered data and complete data source as params

                    FilteredData = FilterHierarchyData(DataSource);

                    DataSource = FilteredData; // assigning new list to datasource and returning

                }

            }

            count = filterCount != null ? FilteredData.Count : count;

            return dm.RequiresCounts ? new DataResult() { Result = DataSource, Count = count } : (object)DataSource;

        }

 

        public List<SelfReferenceData> FilterHierarchyData(IEnumerable<SelfReferenceData> filterData)

        {

            foreach (var data in filterData)

            {

                if (data.ParentID != null)

                {

                    FilteredData = FilterData(data); // calling FilterData method to add parent to new list

                }

                FilteredData.Add(data);//adding filtered data to list

            }

            return FilteredData;

        }

 

        public List<SelfReferenceData> FilterData(SelfReferenceData data)

        {

            var parent = GanttData.Where(p => p.TaskID == data.ParentID).FirstOrDefault();

            if (parent.ParentID != null)

            {

                FilteredData = FilterData(parent);

                FilteredData.Add(parent);

            }

            else

            {

                var alreadyPresent = FilteredData.FindIndex(d => d.TaskID == parent.TaskID);

                if (alreadyPresent == -1)// if parent is not present already, then add parent to list

                {

                    FilteredData.Add(parent);

                    filterCount++; //adding parent data to list

 

                }

            }

            return FilteredData;

        }

    }

 



https://www.syncfusion.com/downloads/support/directtrac/general/ze/Adaptor_(1)-1527209894

Additionally, you can refer to the GitHub sample link for further information on performing CRUD operations.

https://www.syncfusion.com/downloads/support/directtrac/general/ze/Adaptor145135410
https://github.com/SyncfusionExamples/Gantt-Chart-Custom-Adaptor-sample-using-Blazor-server-application

Please note that by implementing the custom adapter and utilizing the filter template, you will be able to have all items visible while still maintaining the functionality of filtering.

Regards,
Ajithkumar G




SZ Szoke June 8, 2023 08:55 PM UTC

HI  Ajithkumar  !


Thank you for your help !


Another question:

How can I save the order of the Gantt tasks, so that they appear in that order the next time I reload?


For example:

From the task in the original order, I move task 56 below task 53.


I would like to save this order(in the database) so that it will appear this way the next time it is loaded.


What can be the solution?


Thank you in advance for your help!




AG Ajithkumar Gopalakrishnan Syncfusion Team June 9, 2023 12:57 PM UTC

Hi Szoke,

We have reviewed your query. To save the order of Gantt tasks and have them appear in the same order upon reloading, we suggest using the dropping event. This event can be used to update the local list of data with the new task order. We have prepared a code snippet and sample to demonstrate this approach.

<GanttEvents RowDropping="RowDroppingHandler" TValue="SelfReferenceData"></GanttEvents>

public
static List<SelfReferenceData> Gantt = new List<SelfReferenceData>();


// Event that is triggered when a row is being dropping

    private void RowDroppingHandler(Syncfusion.Blazor.Grids.RowDroppingEventArgs<SelfReferenceData> args)

    {

        var position = args.Target.ID; // drop position

        var dropIndex = Convert.ToInt32(args.DropIndex); // drop index

        var targetDataID = GanttChart.GetCurrentViewRecords()[dropIndex].TaskID; // drop index data's TaskId

        var targetData = GanttData.Where(ds => ds.TaskID == targetDataID).FirstOrDefault();

        var index = Convert.ToInt32(args.DropIndex);  // drop index

        if (position == " e-droptop" || position == " e-dropbottom") // if a record is dropped below/above another record

        {

            if (args.Data[0].ParentID != null) // if dragged record has parent

            {

                var childCount = 0;

                int parent1 = (int)args.Data[0].ParentID;

                childCount += GetChildRecordsCount(parent1); // finding the number of child for dragged record's parent

                if (childCount == 1) // if the dragged record is the only child for a particular record

                {

                    var i = 0;

                    for (; i < GanttData.Count; i++)

                    {

                        if (GanttData[i].TaskID == parent1)

                        {

                            break;

                        }

                        if (GanttData[i].TaskID == args.Data[0].TaskID)

                        {

                            //set parentItem of dragged record to null

                            GanttData[i].ParentID = null;

                            break;

                        }

                    }

                }

            }

            var data = GanttData.Where(ds => ds.TaskID == args.Data[0].TaskID).FirstOrDefault();

            //removing dragged record from list

            GanttData.Remove(GanttData.Where(ds => ds.TaskID == args.Data[0].TaskID).FirstOrDefault());

            data.ParentID = targetData.ParentID; //setting the dropIndex data's parent as parent of dragged record

 

            if (position == " e-dropbottom") // if a record is dropped below another record

            {

                index = GanttData.IndexOf(targetData);

                index = index + 1;

                GanttData.Insert(index, data);

            }

            else if (position == " e-droptop") // if a record is dropped above another record

            {

                index = GanttData.IndexOf(targetData);

                index = index + GetChildRecordsCount(targetDataID); // find the target record's children count to find drop index

                GanttData.Insert(index, data);

            }

        }

 

        else if (position == " e-dropchild") // if a record is dropped as child to another record(middle segment)

        {

            var data = GanttData.Where(ds => ds.TaskID == args.Data[0].TaskID).FirstOrDefault();

            var dropData = GanttData.Where(ds => ds.TaskID == targetDataID).FirstOrDefault();

            // removing dragged record from list

            GanttData.Remove(GanttData.Where(ds => ds.TaskID == args.Data[0].TaskID).FirstOrDefault());

            data.ParentID = targetDataID; //setting the dropIndex data's ID as parent of dragged record

            index = index + 1;

            GanttData.Insert(index, data);

        }

        GanttData = Gantt = GanttData.ToList();

    }


Sample link: https://www.syncfusion.com/downloads/support/directtrac/general/ze/Adaptor1071812700

 If you have any further concerns or require additional details, please feel free to share them with us.

Regards,
Ajithkumar G



SZ Szoke June 9, 2023 03:15 PM UTC

Dear Ajithkumar 


We use this drag&drop method.

The problem is that not only this can change the order of the Tasks, but e.g. Also on Abow, Below, Child Tasks added from the context menu.

How should these changes be handled in terms of the order set by Task?




AG Ajithkumar Gopalakrishnan Syncfusion Team June 12, 2023 03:36 PM UTC

Hi Szoke,


Query#1: We use this drag&drop method.

Query#2: The problem is that not only this can change the order of the Tasks, but e.g. Also on Abow, Below, Child Tasks added from the context menu.

To achieve this, we can use the actionbegin event. This event can be used to update the local list of data with the new task order. We have prepared a sample and attached it along with a code snippet for your reference.

public override object Insert(DataManager dm, object value, string key)

        {

            GanttData.Insert(0, value as SelfReferenceData);

            Gantt = GanttData.ToList();

            return value;

        }


<Syncfusion.Blazor.Buttons.SfButton OnClick="ReOrder">Reorder</Syncfusion.Blazor.Buttons.SfButton>
….

public
async Task ReOrder()

{

     GanttChart.ReorderRowAsync(4, 3, "Above");

}


public void actionBegin(GanttActionEventArgs<SelfReferenceData> args)

    {

        //Here, you can customize your code.

        if (args.RequestType == Syncfusion.Blazor.Gantt.Action.RowDragAndDrop)

        {   

            var position = "Above"; // drop position

            var dropIndex = 3; // drop index

            var fromIndex = 4; // from index

            var targetDataID = GanttChart.GetCurrentViewRecords()[dropIndex].TaskID; // drop index data's TaskId

            var targetData = GanttData.Where(ds => ds.TaskID == targetDataID).FirstOrDefault();

            var targettingID = GanttChart.GetCurrentViewRecords()[fromIndex].TaskID; // drop index data's TaskId

            var targettingData = GanttData.Where(ds => ds.TaskID == targettingID).FirstOrDefault();

            var index = 3;  // drop index

            if (position == "Above" || position == "Below") // if a record is dropped below/above another record

            {

                if (targettingData.ParentID != null) // if dragged record has parent

                {

                    var childCount = 0;

                    int parent1 = (int)targettingData.ParentID;

                    childCount += GetChildRecordsCount(parent1); // finding the number of child for dragged record's parent

                    if (childCount == 1) // if the dragged record is the only child for a particular record

                    {

                        var i = 0;

                        for (; i < GanttData.Count; i++)

                        {

                            if (GanttData[i].TaskID == parent1)

                            {

                                break;

                            }

                            if (GanttData[i].TaskID == targettingData.TaskID)

                            {

                                //set parentItem of dragged record to null

                                GanttData[i].ParentID = null;

                                break;

                            }

                        }

                    }

                }

                var data = GanttData.Where(ds => ds.TaskID == targettingData.TaskID).FirstOrDefault();

                //removing dragged record from list

                GanttData.Remove(GanttData.Where(ds => ds.TaskID == targettingData.TaskID).FirstOrDefault());

                data.ParentID = targetData.ParentID; //setting the dropIndex data's parent as parent of dragged record

 

                if (position == "Below") // if a record is dropped below another record

                {

                    index = GanttData.IndexOf(targetData);

                    index = index + 1;

                    GanttData.Insert(index, data);

                }

                else if (position == "Above") // if a record is dropped above another record

                {

                    index = GanttData.IndexOf(targetData);

                    index = index + GetChildRecordsCount(targetDataID); // find the target record's children count to find drop index

                    GanttData.Insert(index, data);

                }

            }

 

            else if (position == "Child") // if a record is dropped as child to another record(middle segment)

            {

                var data = GanttData.Where(ds => ds.TaskID == targettingData.TaskID).FirstOrDefault();

                var dropData = GanttData.Where(ds => ds.TaskID == targetDataID).FirstOrDefault();

                // removing dragged record from list

                GanttData.Remove(GanttData.Where(ds => ds.TaskID == targettingData.TaskID).FirstOrDefault());

                data.ParentID = targetDataID; //setting the dropIndex data's ID as parent of dragged record

                index = index + 1;

                GanttData.Insert(index, data);

            }

            GanttData = Gantt = GanttData.ToList();

        }

    }


Sample link: https://www.syncfusion.com/downloads/support/directtrac/general/ze/Adaptor-1999265781

Regards,

Ajithkumar G


Loader.
Up arrow icon