DropDownList with dynamic data

Hi support,
I have a dropdown in a form which is depending on values of other input elements.

The change event of a datepicker (birthday) has to change the possible values of the other dropdown (weightclass).
With the change event everything works fine and the dropdown is populated correctly.
But I have a problem, when I invoke the form the first time.
Then all the possible data in the dropdown is doubled and the dropdown has twice the size.
When I then change the date in the datepicker element, the change event is triggered and everything is fine again.
As you can see below the function called at creating and changing the datepicker is the same.
What am I doing wrong?

This is the dropdown (weightclass) with its datamanager

let weightclassData = new ej.data.DataManager({
url: '<?=$urlBase?>/ageclass/weightclassjson',
adaptor: new ej.data.UrlAdaptor
});

let ddWeightclass = new ej.dropdowns.DropDownList({
value: '<?=$model->weightclass?>',
placeholder: '<?=Yii::t('app', 'Weight Class')?>',
popupHeight: '200px',
floatLabelType: 'Auto',
// query: csrfQuery,
// dataSource: weightclassData,
// fields: {text: 'caption', value: 'value'},
// change: validateDropdown
}, '#athlets-weightclass');


Here is the other code (datepicker and changed event)

new ej.calendars.DatePicker({
format: '<?=CommonHelper::getSFDateFormat()?>',
firstDayOfWeek: <?=Yii::$app->user->identity->firstdayofweek?>,
placeholder: '<?=Yii::t('app', 'Date of Birth')?>',
floatLabelType: 'Auto',
change: birthdayHasChanged,
created: birthdayHasChanged,
}, '#athlets-dateofbirth');

function birthdayHasChanged(args) {
// console.log(args);
// console.log(ddGender.value);
console.log('birthdayHasChanged');
console.log(ddWeightclass.getItems().length);
let val = ddWeightclass.value;
let weightclassQuery = new ej.data.Query().addParams("<?= Yii::$app->request->csrfParam; ?>", "<?= Yii::$app->request->csrfToken; ?>");
weightclassQuery = weightclassQuery.addParams('dateofbirth', document.getElementById('athlets-dateofbirth').value);
weightclassQuery = weightclassQuery.addParams('gender', ddGender.value);
ddWeightclass.dataSource = weightclassData;
ddWeightclass.query = weightclassQuery;
// ddWeightclass.refresh();
ddWeightclass.dataBind();
ddWeightclass.value = val;
console.log(ddWeightclass.getItems().length);
}

It would be great, if you can help me with this issue.
Regards,
Stephan



5 Replies

UD UdhayaKumar Duraisamy Syncfusion Team September 10, 2024 05:05 PM UTC

It seems that the Dropdown List data source is being populated based on the change event of the DatePicker. To properly populate the Dropdown List data source, you can apply a where query to filter the data based on the DatePicker value, as shown in the code snippet below:


        function birthdayHasChanged(args) {

            let val = ddWeightclass.value;

            weightclassQuery = new ej.data.Query().take(10).requiresCount();

            weightclassQuery = datepicker.value != null ? weightclassQuery.where("JoinedDate", "contains", datepicker.value.toLocaleDateString()) : weightclassQuery;

            ddWeightclass.dataSource = weightclassData;

            ddWeightclass.query = weightclassQuery;

            ddWeightclass.value = val;

            ddWeightclass.dataBind();

        }




You can also refer to this sample for further clarity: https://www.syncfusion.com/downloads/support/directtrac/general/ze/dropdown1533679016


If you still encounter issues after implementing the suggestions above, please share the following details to help us better understand your situation and provide a more targeted solution:

  • A modified version of the sample that reflects your specific scenario. This will help us understand how the component is integrated into your project.
  • Detailed steps to replicate the issue.
  • A video illustration demonstrating the problem.


SS Stephan Schrade September 10, 2024 08:31 PM UTC

Hi UdhayaKumar,

many thanks for your reply.

But I think this has nothing to do with the kind of query.

I copied your code to my app.

Because my backend can not deal with these kind of queries, I coded a fixed response no mater what the parameters are.

This is the code:

public function actionWeightclassjson()
{
$response = Yii::$app->response;
$response->format = \yii\web\Response::FORMAT_JSON;
$data = ['-', 'LG'];
$returnData['result'] = $data;
$returnData['count'] = count($data);
$response->data = $returnData;
return $response;
}

So the answer for the dropdown (remote data) will always be the same.

An array with '-' and 'LG'. That's it.

This is the response from the backend:

{

    "result": [

        "-",

        "LG"

    ],

    "count": 2

}

But when I invoke the form for the first time, the dropdown has 4 elements:

'-', 'LG', '-', 'LG'

If I skip the code line to set the dropdown after dataBind(), then the dropdown has no actual value set, but the dropdown itself has the correct elements which is just  '-', 'LG'.

This is the code:

function birthdayHasChanged(args) {
// console.log(args);
// console.log(ddGender.value);
console.log('birthdayHasChanged');
console.log(ddWeightclass.getItems().length);
let val = ddWeightclass.value;
weightclassQuery = new ej.data.Query().take(20).requiresCount();
weightclassQuery = document.getElementById('athlets-dateofbirth').value != null ? weightclassQuery.where("JoinedDate", "contains", document.getElementById('athlets-dateofbirth').value) : weightclassQuery;
ddWeightclass.dataSource = weightclassData;
ddWeightclass.query = weightclassQuery;
// ddWeightclass.refresh();
ddWeightclass.dataBind();
// ddWeightclass.value = val;
console.log(ddWeightclass.getItems().length);
}


So it is not a matter of the query, but something else.

Remember that, the error only occurs, if the form is called for the first time.

If I change the date of birth afterwards, the function birthdayHasChanged() is called again and then the dropdown is refreshed and then has only two elements which is correct.


Regards,

Stephan




UD UdhayaKumar Duraisamy Syncfusion Team September 11, 2024 01:25 PM UTC

Stephan, thank you for sharing the details. Upon reviewing your implementation, it appears that the same data is being returned for each request, and the queries are not being handled properly. When the Dropdown is configured with a remote data source, it first makes an initial request to fetch the data. If a preselected value is bound to the component but is not included in the initial dataset, the component automatically sends a query to retrieve that specific preselected value from the backend. This ensures the preselected value is displayed correctly, even if it wasn't part of the initial data load.


In your case, since the same data is returned for each request, it causes duplication of data items in the Dropdown List popup.


To resolve this, we suggest properly handling the query on the server side to return only the necessary data and prevent duplication. Alternatively, it seems that each time the DatePicker value changes, you are reassigning the data source to the Dropdown List. In such cases, you can try clear the existing items in the Dropdown List before assigning the new data source to avoid duplications.


Please refer to the code snippet below for reference:

function birthdayHasChanged(args) {

    console.log('birthdayHasChanged');

    console.log(ddWeightclass.getItems().length);

 

    // Clear the existing items in the dropdown

    ddWeightclass.dataSource = [];

    ddWeightclass.dataBind();

 

    let val = ddWeightclass.value;

    weightclassQuery = new ej.data.Query().take(20).requiresCount();

    weightclassQuery = document.getElementById('athlets-dateofbirth').value != null ? weightclassQuery.where("JoinedDate", "contains", document.getElementById('athlets-dateofbirth').value) : weightclassQuery;

 

    // Set the new data source

    ddWeightclass.dataSource = weightclassData;

    ddWeightclass.query = weightclassQuery;

    ddWeightclass.dataBind();

 

    // Optionally set the value back if needed

    // ddWeightclass.value = val;

 

    console.log(ddWeightclass.getItems().length);

}



SS Stephan Schrade September 11, 2024 03:00 PM UTC

Hello UdhayaKumar,

many thanks for your suggestions.

Unfortunately it does not help.

I noticed, that my backend for the dropdown data is always called twice when I open the form for the very first time.

The first comes from setting the dataSource, the second on from setting the value.

And they are overlapping.

If I do set the value 3sec after calling dataBind(), everything works perfect. Then the backend is only invoked once.

Here is the code:

function birthdayCreated(args) {
// console.log(args);
// console.log(ddGender.value);
console.log('birthdayCreated');
console.log(ddWeightclass.getItems().length);
// ddWeightclass.value = null;
// ddWeightclass.dataSource = [];
// ddWeightclass.dataBind();
let weightclassQuery = new ej.data.Query().addParams("<?= Yii::$app->request->csrfParam; ?>", "<?= Yii::$app->request->csrfToken; ?>");
weightclassQuery = weightclassQuery.addParams('dateofbirth', document.getElementById('athlets-dateofbirth').value);
weightclassQuery = weightclassQuery.addParams('gender', ddGender.value);
ddWeightclass.query = weightclassQuery;
ddWeightclass.dataSource = weightclassData;
// ddWeightclass.refresh();
ddWeightclass.dataBind();
setTimeout(() => {
ddWeightclass.value = '<?=$model->weightclass?>';
}, 3000)
console.log(ddWeightclass.getItems().length);
}

But this is not so satisfying. Are 3sec always enough or perhaps too much?

Setting the value after the event dataBound or actionComplete did not work.

Regards,

Stephan



UD UdhayaKumar Duraisamy Syncfusion Team September 12, 2024 03:50 PM UTC

Stephan, To assist you more effectively, please share or modify the provided sample to fit your current scenario. This will help us understand how the component is integrated, how the queries are being handled, and the response returned in your application. By doing so, we can offer a more precise and prompt solution tailored to your specific implementation.


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


Loader.
Up arrow icon