sw-entity-listing: 无法读取未定义的属性(读取 ‘page’)

huangapple go评论86阅读模式
英文:

sw-entity-listing: Cannot read properties of undefined (reading 'page')

问题

在我的管理界面中,我正在使用sw-entity-listing组件,用于加载自定义实体的条目。该列表有四列(客户组、销售渠道、产品和最大数量)。客户组和销售渠道包含一个ID,而产品包含一个包含ID的JSON。

我试图做的是将这些ID映射到实际的实体名称。为此,我创建了以下JS代码:

getList() {
    this.isLoading = true;
    const criteria = new Criteria();
    return this.cartCrossSellRepository.search(criteria, Shopware.Context.api).then(async (result) => {
        this.total = result.total;

        const cartCrossSell = result.map(async (item) => {
            const customerGroup = await this.getCustomerGroupName(item.customerGroupId);
            const salesChannel = await this.getSalesChannelName(item.salesChannelId);
            const products = await this.getProductNames(item.products);

            return {
                ...item,
                customerGroup,
                salesChannel,
                products
            };
        });

        this.cartCrossSell = await Promise.all(cartCrossSell);
        this.isLoading = false;
    });
},

async getCustomerGroupName(customerGroupId) {
    const criteria = new Criteria();
    criteria.addFilter(Criteria.equals('id', customerGroupId));

    const customerGroup = await this.customerGroupRepository.search(criteria, Shopware.Context.api);
    return customerGroup[0].translated.name;
},

async getSalesChannelName(salesChannelId) {
    const criteria = a Criteria();
    criteria.addFilter(Criteria.equals('id', salesChannelId));

    const salesChannel = await this.salesChannelRepository.search(criteria, Shopware.Context.api);
    return salesChannel[0].translated.name;
},

async getProductNames(productIds) {
    const criteria = new Criteria();
    criteria.setIds(productIds);

    const products = await this.productRepository.search(criteria, Shopware.Context.api);
    const productNames = products.map((product) => product.productNumber);

    return productNames.join('<br>');
}

一切都运行良好,但是我的控制台日志中出现了一个错误:在当前模块中捕获到一个错误:TypeError: 无法读取未定义的属性(读取'page')

当我使用类似以下代码时,错误会消失,但我失去了数据映射功能:

getList() {
    this.isLoading = true;
    const criteria = new Criteria();
    return this.cartCrossSellRepository.search(criteria, Shopware.Context.api).then((result) => {
        this.total = result.total;
        this.cartCrossSell = result;
        this.isLoading = false;
    })
}

由于这个错误,组件的删除功能无法按预期工作(删除后页面没有重新加载并且被冻结)。是什么原因导致了这个问题,我该如何解决?

英文:

In the administration I'm using the sw-entity-listing component where I load the entries of a custom entity. The listing has four columns (customer group, sales channel, products and maxcount). customer group and sales channel contains an ID and products contains an JSON with ID's.

What I'm trying to do is map the ID's to the actual entity names. For that part I've created this JS:

getList() {
            this.isLoading = true;
            const criteria = new Criteria();
            return this.cartCrossSellRepository.search(criteria, Shopware.Context.api).then(async (result) =&gt; {
                this.total = result.total;

                const cartCrossSell = result.map(async (item) =&gt; {
                    const customerGroup = await this.getCustomerGroupName(item.customerGroupId);
                    const salesChannel = await this.getSalesChannelName(item.salesChannelId);
                    const products = await this.getProductNames(item.products);

                    return {
                        ...item,
                        customerGroup,
                        salesChannel,
                        products
                    };
                });

                this.cartCrossSell = await Promise.all(cartCrossSell);
                this.isLoading = false;
            });
        },

        async getCustomerGroupName(customerGroupId) {
            const criteria = new Criteria();
            criteria.addFilter(Criteria.equals(&#39;id&#39;, customerGroupId));

            const customerGroup = await this.customerGroupRepository.search(criteria, Shopware.Context.api);
            return customerGroup[0].translated.name;
        },

        async getSalesChannelName(salesChannelId) {
            const criteria = new Criteria();
            criteria.addFilter(Criteria.equals(&#39;id&#39;, salesChannelId));

            const salesChannel = await this.salesChannelRepository.search(criteria, Shopware.Context.api);
            return salesChannel[0].translated.name;
        },

        async getProductNames(productIds) {
            const criteria = new Criteria();
            criteria.setIds(productIds);

            const products = await this.productRepository.search(criteria, Shopware.Context.api);
            const productNames = products.map((product) =&gt; product.productNumber);

            return productNames.join(&#39;&lt;br&gt;&#39;);
        }

All is working fine but I'm getting an error in my console log: An error was captured in current module: TypeError: Cannot read properties of undefined (reading &#39;page&#39;).

When I use something like this the error is gone but then I don't have the data mapping:

getList() {
			this.isLoading = true;
			const criteria = new Criteria();
			return this.cartCrossSellRepository.search(criteria, Shopware.Context.api).then((result) =&gt; {
				this.total = result.total;
				this.cartCrossSell = result;
				this.isLoading = false;
			})
		}

Because of the error, the delete function of the component isn't working as expected (page isn't reloading after delete and freezes). What is causing the problem and how can I fix this?

答案1

得分: 2

以下是您要翻译的内容:

"The listing is expecting a type of EntityCollection which the search call on the repository would normally return. You however return an array of generic objects by mapping the original result. There are a few things that don't seem optimal here. You obviously have a foreign key to customer_group, as well as sales_channel. So I assume your entity definition partially looks like this:

new FkField('customer_group_id', 'customerGroupId', CustomerGroupDefinition::class),
new FkField('sales_channel_id', 'salesChannelId', SalesChannelDefinition::class),
new ManyToOneAssociationField('customerGroup', 'customer_group_id', CustomerGroupDefinition::class, 'id'),
new ManyToOneAssociationField('salesChannel', 'sales_channel_id', SalesChannelDefinition::class, 'id'),

Then you could simply add the corresponding association to the criteria when fetching the entities by the cartCrossSellRepository. That way, you wouldn't have to fetch individual instances of sales_channel and customer_group on each iteration, making the whole procedure much more performant.

const criteria = new Criteria();
criteria.addAssociation('customerGroup');
criteria.addAssociation('salesChannel');

this.cartCrossSellRepository.search(criteria, Shopware.Context.api).then(async (result) => {
    result.forEach((item) => {
        // should log the respective entity data fetched by association
        console.log(item.customerGroup);
        console.log(item.salesChannel);
    });
});

For the products you ideally should also use the corresponding association as well. However it seems like your products property is just a json field containing the ids? I would advise to make it a proper ManyToManyAssociationField if not already the case.

If you want to stick with your current approach, you could simply iterate the items of the EntityCollection and set your additional data as an unmapped property to the entity.

this.cartCrossSellRepository.search(criteria, Shopware.Context.api).then(async (result) => {
    result.forEach((item) => {
        item.productNames = await this.getProductNames(item.products);
    });

    return result;
});
英文:

The listing is expecting a type of EntityCollection which the search call on the repository would normally return. You however return an array of generic objects by mapping the original result. There are a few things that don't seem optimal here. You obviously have a foreign key to customer_group, as well as sales_channel. So I assume your entity definition partially looks like this:

new FkField(&#39;customer_group_id&#39;, &#39;customerGroupId&#39;, CustomerGroupDefinition::class),
new FkField(&#39;sales_channel_id&#39;, &#39;salesChannelId&#39;, SalesChannelDefinition::class),
new ManyToOneAssociationField(&#39;customerGroup&#39;, &#39;customer_group_id&#39;, CustomerGroupDefinition::class, &#39;id&#39;),
new ManyToOneAssociationField(&#39;salesChannel&#39;, &#39;sales_channel_id&#39;, SalesChannelDefinition::class, &#39;id&#39;),

Then you could simply add the corresponding association to the criteria when fetching the entities by the cartCrossSellRepository. That way, you wouldn't have to fetch individual instances of sales_channel and customer_group on each iteration, making the whole procedure much more performant.

const criteria = new Criteria();
criteria.addAssociation(&#39;customerGroup&#39;);
criteria.addAssociation(&#39;salesChannel&#39;);

this.cartCrossSellRepository.search(criteria, Shopware.Context.api).then(async (result) =&gt; {
    result.forEach((item) =&gt; {
        // should log the respective entity data fetched by association
        console.log(item.customerGroup);
        console.log(item.salesChannel);
    });
});

For the products you ideally should also use the corresponding association as well. However it seems like your products property is just a json field containing the ids? I would advise to make it a proper ManyToManyAssociationField if not already the case.

If you want to stick with your current approach, you could simply iterate the items of the EntityCollection and set your additional data as an unmapped property to the entity.

this.cartCrossSellRepository.search(criteria, Shopware.Context.api).then(async (result) =&gt; {
    result.forEach((item) =&gt; {
        item.productNames = await this.getProductNames(item.products);
    });

    return result;
});

huangapple
  • 本文由 发表于 2023年8月9日 17:13:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866232-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定