
# List dynamic editor

You can dynamically output a dropdown list from a single column rather than a lookupTree structure.

#### Apply listCallback

You can use it dynamically by directly filling in the values corresponding to the value and label in the editor.listCallback function, or return it as a value retrieved from the DB to dynamically display the desired list values.
In templateCallback, you can process and output images or value to be displayed on the screen directly using information obtained from listCallback.

Since lookupDisplay is not applied to listCallback, the selected value is displayed by default.
If you need a dynamic list and lookup, you should use the lookupTree function.


```js
const fields = [
  { fieldName: "Country" },
  { fieldName: "Currency" },
  { fieldName: "CountryCode" }
];

const columns = [
  {
    name: "Country",
    fieldName: "Country",
    width: "150",
    lookupDisplay: true,
    editButtonVisibility: "always",
    editor: {
      type: "list",
      listCallback: function(grid, index) {
        return {
          value: "value",
          label: "label",
          list: [
            { value: "Korea", label: "Korea", flag: "KR", country: "Korea", currency: "KRW" },
            { value: "USA", label: "USA", flag: "US", country: "USA", currency: "USD" },
            { value: "Brazil", label: "Brazil", flag: "BR", country: "Brazil", currency: "BRL" },
            { value: "Argentina", label: "Argentina", flag: "AR", country: "Argentina", currency: "ARS" },
            { value: "China", label: "China", flag: "CN", country: "China", currency: "CNY" },
            { value: "Japan", label: "Japan", flag: "JP", country: "Japan", currency: "JPY" }
          ]
        };
      },
      templateCallback: function(grid, index, div, value, label, item) {
        div.innerHTML = `<span style='width:100px'>value: ${value}</span>
                         <span style='width:100px'>, label: ${label}</span>`;
      }
    },
    header: { text: "Country" }
  },
  {
    name: "Currency",
    fieldName: "Currency",
    header: { text: "Currency" }
  },
  {
    name: "CountryCode",
    fieldName: "CountryCode",
    header: { text: "Country Code" }
  }
];

const { gridView, dataProvider } = RealGrid.createGrid("realgrid", {
  columns,
  header: { height: 40 },
  display: { rowHeight: 36, emptyMessage: "No data to display." },
  footer: { height: 40 },
  stateBar: { width: 16 },
  edit: { insertable: true, appendable: true },
  onGetEditValue: (grid, index, result) => {
    if (index.column === "Country" && result["item"]) {
      grid.setValue(index.itemIndex, "Currency", result["item"].currency);
      grid.setValue(index.itemIndex, "CountryCode", result["item"].flag);
    }
  },
  onInitialized: (grid) => {
    grid.getDataSource().setRows([
      { Country: "Korea", Currency: "KRW", CountryCode: "KR" },
      { Country: "USA", Currency: "USD", CountryCode: "US" },
      { Country: "Brazil", Currency: "BRL", CountryCode: "BR" },
      { Country: "Argentina", Currency: "ARS", CountryCode: "AR" },
      { Country: "Korea", Currency: "KRW", CountryCode: "KR" },
      { Country: "USA", Currency: "USD", CountryCode: "US" },
      { Country: "Brazil", Currency: "BRL", CountryCode: "BR" },
      { Country: "Argentina", Currency: "ARS", CountryCode: "AR" },
      { Country: "Korea", Currency: "KRW", CountryCode: "KR" },
      { Country: "USA", Currency: "USD", CountryCode: "US" },
      { Country: "Brazil", Currency: "BRL", CountryCode: "BR" },
      { Country: "Argentina", Currency: "ARS", CountryCode: "AR" }
    ]);
  }
}, {
  fields
});

window.gridView = gridView;
window.dataProvider = dataProvider;
```

```js
var columns = [{
    name: "Country",
    fieldName: "Country",
    width: "150",
    editButtonVisibility: "always",
    editor:{
        type: "list",
        listCallback: function(grid, index) {
          return {
            value: "value", // Same form as column.listData. The value and label attributes can be omitted.
            label: "label",  // 
            list: [ {value: "Korea", label: "한국", flag: "KR", country: "Korea", currency: "KRW"},
                    {value: "USA", label: "미국", flag: "US", country: "USA", currency: "USD"},
                    {value: "Brazil", label: "브라질", flag: "BR", country: "Brazil", currency: "BRL"},
                    {value: "Argentina", label: "아르헨티나", flag: "AR", country: "Argentina", currency: "ARS"},
                    {value: "China", label: "중국", flag: "CN", country: "China", currency: "CNY"},
                    {value: "Japan", label: "일본", flag: "JP", country: "Japan", currency: "JPY"}
            ]
          }
        },
        templateCallback: function(grid, index, div, value, label, item) {
            div.innerHTML = `<span style='width:100px'>value: ${value}</span>
                             <span style='width:100px'>, label: ${label}</span>`
        }
      },
    header: {
        text: "나라",
    }
  }
  ...
]

//value change event
gridView.onGetEditValue = (grid,index,result)=>{
    if (index.column === "Country" && result["item"]) {
        grid.setValue(index.itemIndex, "Currency", result["item"].currency);
        grid.setValue(index.itemIndex, "CountryCode", result["item"].flag);
    }
  }
```


#### Apply labelField

In order to display on the grid the value corresponding to the label rather than the value, you must apply the labelField function and set the value in labelField.

```js
const fields = [
  { fieldName: "Country" },
  { fieldName: "Currency" },
  { fieldName: "CountryCode" },
  { fieldName: "labelField" }
];

const columns = [
  {
    name: "Country",
    fieldName: "Country",
    width: "150",
    lookupDisplay: true,
    labelField: "labelField",
    editButtonVisibility: "always",
    editor: {
      type: "list",
      listCallback: function(grid, index) {
        return {
          value: "value",
          label: "label",
          list: [
            { value: "Korea", label: "Korea", flag: "KR", country: "Korea", currency: "KRW" },
            { value: "USA", label: "USA", flag: "US", country: "USA", currency: "USD" },
            { value: "Brazil", label: "Brazil", flag: "BR", country: "Brazil", currency: "BRL" },
            { value: "Argentina", label: "Argentina", flag: "AR", country: "Argentina", currency: "ARS" },
            { value: "China", label: "China", flag: "CN", country: "China", currency: "CNY" },
            { value: "Japan", label: "Japan", flag: "JP", country: "Japan", currency: "JPY" }
          ]
        };
      },
      templateCallback: function(grid, index, div, value, label, item) {
        div.innerHTML = `<span style='width:100px'>value: ${value}</span>
                         <span style='width:100px'>, label: ${label}</span>`;
      }
    },
    header: { text: "Country" }
  },
  {
    name: "Currency",
    fieldName: "Currency",
    header: { text: "Currency" }
  },
  {
    name: "CountryCode",
    fieldName: "CountryCode",
    header: { text: "Country Code" }
  },
  {
    name: "labelField",
    fieldName: "labelField",
    header: { text: "labelField" }
  }
];

const { gridView, dataProvider } = RealGrid.createGrid("realgrid", {
  columns,
  header: { height: 40 },
  display: { rowHeight: 36, emptyMessage: "No data to display." },
  footer: { height: 40 },
  stateBar: { width: 16 },
  edit: { insertable: true, appendable: true },
  onGetEditValue: (grid, index, result) => {
    if (index.column === "Country" && result["item"]) {
      grid.setValue(index.itemIndex, "Currency", result["item"].currency);
      grid.setValue(index.itemIndex, "CountryCode", result["item"].flag);
      grid.setValue(index.itemIndex, "labelField", result["item"].label);
    }
  },
  onInitialized: (grid) => {
    grid.getDataSource().setRows([
      { Country: "Korea", Currency: "KRW", CountryCode: "KR", labelField: "Korea" },
      { Country: "USA", Currency: "USD", CountryCode: "US", labelField: "USA" },
      { Country: "Brazil", Currency: "BRL", CountryCode: "BR", labelField: "Brazil" },
      { Country: "Argentina", Currency: "ARS", CountryCode: "AR", labelField: "Argentina" },
      { Country: "Korea", Currency: "KRW", CountryCode: "KR", labelField: "Korea" },
      { Country: "USA", Currency: "USD", CountryCode: "US", labelField: "USA" },
      { Country: "Brazil", Currency: "BRL", CountryCode: "BR", labelField: "Brazil" },
      { Country: "Argentina", Currency: "ARS", CountryCode: "AR", labelField: "Argentina" }
    ]);
  }
}, {
  fields
});

window.gridView = gridView;
window.dataProvider = dataProvider;
```

```js
//Column settings, label field application
var columns = [{
    name: "Country",
    fieldName: "Country",
    width: "150",
    lookupDisplay: true,
    labelField: "labelField",
    editButtonVisibility: "always",
    editor:{
        type: "list",
        listCallback: function(grid, index) {
          return {
            value: "value", // Same form as column.listData. The value and label attributes can be omitted.
            label: "label",  // 
            list: [ {value: "Korea", label: "한국", flag: "KR", country: "Korea", currency: "KRW"},
                    {value: "USA", label: "미국", flag: "US", country: "USA", currency: "USD"},
                    {value: "Brazil", label: "브라질", flag: "BR", country: "Brazil", currency: "BRL"},
                    {value: "Argentina", label: "아르헨티나", flag: "AR", country: "Argentina", currency: "ARS"},
                    {value: "China", label: "중국", flag: "CN", country: "China", currency: "CNY"},
                    {value: "Japan", label: "일본", flag: "JP", country: "Japan", currency: "JPY"}
            ]
          }
        },
        templateCallback: function(grid, index, div, value, label, item) {
            div.innerHTML = `<span style='width:100px'>value: ${value}</span>
                             <span style='width:100px'>, label: ${label}</span>`
        }
      },
    header: {
        text: "나라",
    }
  },
  ...
]

//Apply label field value when changing value
gridView.onGetEditValue = (grid,index,result)=>{
    if (index.column === "Country" && result["item"]) {
        grid.setValue(index.itemIndex, "Currency", result["item"].currency);
        grid.setValue(index.itemIndex, "CountryCode", result["item"].flag);
        grid.setValue(index.itemIndex, "labelField", result["item"].label);
    }
}

//Filling in label field values when querying
dataProvider.setRows([
    {Country: "Korea", Currency: "KRW", CountryCode: "KR", labelField: "한국"},
    {Country: "USA", Currency: "USD", CountryCode: "US", labelField: "미국"},
    {Country: "Brazil", Currency: "BRL", CountryCode: "BR", labelField: "브라질"},
    {Country: "Argentina", Currency: "ARS", CountryCode: "AR", labelField: "아르헨티나"},
    {Country: "Korea", Currency: "KRW", CountryCode: "KR", labelField: "한국"},
    {Country: "USA", Currency: "USD", CountryCode: "US", labelField: "미국"},
    {Country: "Brazil", Currency: "BRL", CountryCode: "BR", labelField: "브라질"},
    {Country: "Argentina", Currency: "ARS", CountryCode: "AR", labelField: "아르헨티나"}
  ])
```

#### List setting through asynchronous processing  

Using listCallback allows you to dynamically populate the list with desired data through asynchronous processing.   
This is particularly useful when you need to fetch data from the server to generate the list dynamically. 

```js
const fields = [
  { fieldName: "Category", dataType: "text" },
  { fieldName: "Menu", dataType: "text" },
  { fieldName: "MenuLabelField", dataType: "text" }
];

function getCategoryIndex(category) {
  const categories = ["Korean Food", "Chinese Food", "Japanese Food", "Form", "Dessert", "Fast Food"];
  return categories.indexOf(category) + 1;
}

async function getLists(categoryIndex, grid) {
  return new Promise((resolve, reject) => {
    grid.showLoading(true);
    const url = `list${categoryIndex}.json`;
    fetch(url)
      .then(response => {
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        return response.json();
      })
      .then(data => {
        setTimeout(() => {
          grid.closeLoading();
          resolve({
            value: "value",
            label: "label",
            list: data
          });
        }, 500);
      })
      .catch(error => {
        console.log(error);
        grid.closeLoading();
        reject(error);
      });
  });
}

const columns = [
  {
    name: "Category",
    fieldName: "Category",
    width: "150",
    header: { text: "Category" }
  },
  {
    name: "Menu",
    fieldName: "Menu",
    width: "150",
    lookupDisplay: true,
    labelField: "MenuLabelField",
    editButtonVisibility: "always",
    editor: {
      type: "list",
      listCallback: async (grid, index) => {
        const category = grid.getValue(index.itemIndex, 'Category');
        const categoryIndex = getCategoryIndex(category);
        return await getLists(categoryIndex, grid);
      }
    },
    header: { text: "Menu" }
  },
  {
    name: "MenuLabelField",
    fieldName: "MenuLabelField",
    header: { text: "Label Field" }
  }
];

const { gridView, dataProvider } = RealGrid.createGrid("realgrid", {
  columns,
  header: { height: 40 },
  display: { rowHeight: 36, emptyMessage: "No data to display." },
  footer: { height: 40 },
  stateBar: { width: 16 },
  edit: { insertable: true, appendable: true },
  onGetEditValue: (grid, index, result) => {
    if (index.column === "Menu") {
      const value = result["item"] ? result["item"].label : result["text"];
      grid.setValue(index.itemIndex, "MenuLabelField", value);
    }
  },
  onInitialized: (grid) => {
    fetch('/data/en/listcallback_data.json')
      .then(response => response.json())
      .then(data => {
        grid.getDataSource().setRows(data);
      });
  }
}, {
  fields
});

window.gridView = gridView;
window.dataProvider = dataProvider;
```

```js
var columns = [
  {
      name: "Menu",
      fieldName: "Menu",
      width: "150",
      lookupDisplay: true,
      labelField: "MenuLabelField", // 라벨 필드를 통해 value 값이 아닌 label 값이 화면에 보여질 수 있도록 연결
      editButtonVisibility: "always",
      editor: {
          type: "list",
          listCallback: async (grid, index) => {
              const category = grid.getValue(index.itemIndex, 'Category');
              const categoryIndex = getCategoryIndex(category);
              return await getLists(categoryIndex, grid);
          },
      },
      header: {
          text: "메뉴",
      },
  },
  ...
];

function getCategoryIndex(category) {
  const categories = ["한식", "중식", "일식", "양식", "디저트", "패스트푸드"];
  return categories.indexOf(category) + 1;
}

async function getLists(categoryIndex, grid) {www
  return new Promise((resolve, reject) => {
      grid.showLoading(true);
      const url = `list${categoryIndex}.json`
      $.ajax({
          url: url,
          type: "GET",
          dataType: "json",
          success: function (data) {
              setTimeout(() => {
                  grid.closeLoading();
                  resolve({
                      value: "value",
                      label: "label",
                      list: data,
                  });
              }, 500);
          },
          error: function (xhr, status, error) {
              grid.closeLoading();
              reject(error);
          },
      });
  });
}
```