简体   繁体   English

如何使用 ion-reorder 对分组项目进行重新排序

[英]How to reorder grouped items with ion-reorder

I'm trying to use ion-reorder to reorder some items in a page.我正在尝试使用ion-reorder对页面中的某些项目进行重新排序。 These item are organized in groups, so a group has several items.这些项目按组组织,因此一个组有多个项目。 I want to organize these items inside the group, but more importantly I want to be able to change the item from a group to another.我想在组内组织这些项目,但更重要的是我希望能够将项目从一个组更改为另一个组。

I'm facing 2 problems currently:我目前面临两个问题:

  • I can't update the array, consequently the item orders are not show correctly when changed.我无法更新数组,因此项目订单在更改时无法正确显示。
  • I can't move a item outside it's group, consequently I can't move to another group.我无法将某个项目移出它的组,因此我无法移动到另一个组。

html html

<ion-content>   
    <ion-list *ngFor='let group of groupArray'>
        <ion-reorder-group (ionItemReorder)="doReorder($event)" disabled="false">
            <ion-list-header>{{group.name}}</ion-list-header>           
            <ion-item *ngFor='let item of group.items'>
                <ion-reorder slot="start"></ion-reorder>
                <ion-label>
                    {{item.name}}
                </ion-label>
            </ion-item>
        </ion-reorder-group>
    </ion-list>     
</ion-content>

typescript typescript

interface Item {
    id: number,
    name: string
}
interface Group {
    name: string,
    items: Item[]
}
interface GroupArray extends Array<Group>{}

...

private groupArray: GroupArray = [
    {
        name: 'FirstGroup',
        items: [
            {
                id: 1,
                name: 'FirstItem'
            },{
                id: 2,
                name: 'SecondItem'
            },{
                id: 3,
                name: 'ThirdItem'
            }
        ]
    },
    {
        name: 'SecondGroup',
        items: [
            {
                id: 4,
                name: 'FourthItem'
            },{
                id: 5,
                name: 'FifthItem'
            },{
                id: 6,
                name: 'SixthItem'
            }
        ]
    }       
];

/** Reorder */
doReorder(ev: CustomEvent<ItemReorderEventDetail>) {
    this.groupArray = ev.detail.complete(this.groupArray);
}

I tried to move the <ion-reorder-group> to several positions, but this is the only one I managed to move the correct items.我试图将<ion-reorder-group>移动到多个位置,但这是我唯一成功移动正确项目的位置。 If I move up, above <ion-list> , the whole list becomes draggable and I can't move the item.如果我向上移动,在<ion-list>上方,整个列表变得可拖动,我无法移动该项目。

I understand that this is happening because the <ion-reorder-group> is created 2 times, but I can't think in a way to create only one time and maintain the same aspect, which is exactly like the documentation page that I linked.我知道这是因为<ion-reorder-group>创建了 2 次,但我想不出只创建一次并保持相同方面的方式,这与我链接的文档页面完全一样. The difference is that in there they load the items individually, and the groups are just another item that can be drag around.不同之处在于,他们在那里单独加载项目,而组只是另一个可以拖动的项目。

The other problem I believe is related to how complete() works.我认为另一个问题与complete()的工作方式有关。 Although it expects any[] as a parameter, I don't think it was made to support a complex structure, just a simple array.虽然它期望any[]作为参数,但我不认为它是为了支持复杂的结构而设计的,只是一个简单的数组。

How can I solve these two problems?我该如何解决这两个问题?


I'm using Ionic 5 with Angular 10我将 Ionic 5 与 Angular 10 一起使用

StackBlitz 堆栈闪电战

For the reording issue, you have two things对于重新排序问题,您有两件事

  • You are sending the wrong items to the complete function, it should be the rendered items ( groupArray[index].items ), not the root object itself ( groupArray ).您将错误的项目发送到complete的 function,它应该是呈现的项目( groupArray[index].items ),而不是根 object 本身( groupArray )。
  • The ion-list-header should be above the ion-reorder-group , so Ionic won't treat it as a child of the ion-reorder-group and mess up the reording logic for the array. ion-list-header应该在ion-reorder-group之上,因此 Ionic 不会将其视为ion-reorder-group的子级,并且会弄乱数组的重新排序逻辑。

Even though the example in the attached link for the ion-reorder is using one big ion-reorder-group and the ion-list-header to add some list headers, but this won't work if you need to update the array using the complete .即使ion-reorder 附加链接中的示例使用一个大ion-reorder-groupion-list-header添加一些列表标题,但如果您需要使用更新数组,这将不起作用complete

You can do something like this to make it work:你可以做这样的事情来使它工作:

doReorder(ev: CustomEvent<ItemReorderEventDetail>, groupId: number) {
  let groupToChangeIndex = this.groupArray.findIndex(
    group => group.id === groupId
  );
  this.groupArray[groupToChangeIndex].items = ev.detail.complete(
    this.groupArray[groupToChangeIndex].items
  );
}

HTML: HTML:

<ion-content>
  <ion-list *ngFor='let group of groupArray'>
    <ion-list-header>{{group.name}}</ion-list-header>
    <ion-reorder-group (ionItemReorder)="doReorder($event, group.id)" disabled="false">
      <ion-item *ngFor='let item of group.items'>
        <ion-reorder slot="start"></ion-reorder>
        <ion-label>
          {{item.name}}
        </ion-label>
      </ion-item>
    </ion-reorder-group>
  </ion-list>
</ion-content>

At the same time, you can't move an ion-item from one group to another.同时,您不能将离子项目从一组移动到另一组。 What I can think of for handling this issue is to have one big ion-reorder-group with the ion-list-header , and do the reording manually.我能想到的处理这个问题是有一个大ion-reorder-groupion-list-header ,并手动进行重新排序。 Accessing the target property from the event that was sent to the doReorder function, then you can access the children, filter only the ion-item then reflect the sorting to the array (even though it is a very ugly workaround).从发送到doReorder function 的事件中访问target属性,然后您可以访问子项,仅过滤ion-item然后将排序反映到数组中(即使这是一个非常丑陋的解决方法)。


Update更新

I actually thought of a better solution.我实际上想到了一个更好的解决方案。 You can create a new array that contains all the items flattened.您可以创建一个包含所有展平项目的新数组。 Then when you want to submit you changes, there will be a function that will create the new order for you.然后,当您要提交更改时,将会有一个 function 将为您创建新订单。 You can check the following Stackblitz: https://stackblitz.com/edit/ionic-5-angular-10-start-template-zasssd?file=src/app/tab1/tab1.page.ts您可以检查以下 Stackblitz: https://stackblitz.com/edit/ionic-5-angular-10-start-template-zasssd?file=src/app/tab1/tab1.page.ts

constructor() {
  this.allItemsFlattened = this.groupArray.flatMap((group, index) => [
    { isHeader: true, index: index, name: group.name },
    ...group.items
  ]);
}

/** Reorder objects in array */
doReorder(ev: CustomEvent<ItemReorderEventDetail>) {
  this.allItemsFlattened = ev.detail.complete(this.allItemsFlattened);
}

getRightOrder() {
  const rightOrder = this.allItemsFlattened.reduce((accumlator, item) => {
    if (item.isHeader) {
      const { id, name, ...rest } = this.groupArray[item.index];
      accumlator.push({ id, name, items: [] });
    } else {
      accumlator[accumlator.length - 1].items.push(item);
    }
    return accumlator;
  }, []);
  console.log(rightOrder);
}

I personally used this approach.我个人使用了这种方法。

ngOnint(){
this.item.items = result[1]; 

if (this.item?.itemSortOrder != null) {
// converting string to array
let itemSortOrder= this.item.itemSortOrder.split(","); 

this.newIndexArray = itemSortOrder
                           .map((i) => this.item.items.find((j) => j.id === i))
                           .filter(e => e !== undefined && e !== null); 
    }}
    
doReorder(ev: CustomEvent<ItemReorderEventDetail>) {
    console.log('Dragged from index', ev.detail.from, 'to', ev.detail.to);
    this.newIndexArray = ev.detail.complete(this.newIndexArray);
  }

saveReorder() {
    let newOrderPosition: string[] = [];
    this.newIndexArray.forEach((x) => {
      newOrderPosition.push(x.id); //adding sorted new item id's to an array
    })

    //array to string
    this.item.itemSortOrder = newOrderPosition.toString();

   //Passing the newArray order of items to the server
    this.newService.updateCatalog(this.item)
      .subscribe((result) => {
        console.log(result);
      });
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM