当前位置: 首页 > 知识库问答 >
问题:

当列是JSON数组而不是字符串时,如何对ANTD表进行筛选

皇甫宇定
2023-03-14

我有一个包含两列的antd表,第一列需要过滤,第二列需要搜索文本。

根据我的代码,应用程序呈现良好。请注意,tags字段是一个json数组,而不是文本字段,所以我想这与错误有关。

更新1代码。

import React, { Component } from 'react';
import {  Table, Tag, Button, Icon, Input} from 'antd';
import { adalApiFetch } from '../../adalConfig';
import Notification from '../../components/notification';
import Highlighter from 'react-highlight-words';

class ListPageTemplatesWithSelection extends Component {

    constructor(props) {
        super(props);
        this.state = {
            data: [],
            filteredInfo: null,
            sortedInfo: null,
            searchText: ''
        };
        this.handleChange= this.handleChange.bind(this);
        this.clearFilters= this.clearFilters.bind(this);
        this.clearAll= this.clearAll.bind(this);
        this.getColumnSearchProps= this.getColumnSearchProps.bind(this);
        this.handleSearch= this.handleSearch.bind(this);
        this.handleReset= this.handleReset.bind(this);

    }

    handleSearch (selectedKeys, confirm){
      confirm();
      this.setState({ searchText: selectedKeys[0] });
    }

    handleReset(clearFilters){
      clearFilters();
      this.setState({ searchText: '' });
    }

    getColumnSearchProps = (dataIndex) => ({
        filterDropdown: ({
        setSelectedKeys, selectedKeys, confirm, clearFilters,
      }) => (
        <div style={{ padding: 8 }}>
          <Input
            ref={node => { this.searchInput = node; }}
            placeholder={`Search ${dataIndex}`}
            value={selectedKeys[0]}
            onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
            onPressEnter={() => this.handleSearch(selectedKeys, confirm)}
            style={{ width: 188, marginBottom: 8, display: 'block' }}
          />
          <Button
            type="primary"
            onClick={() => this.handleSearch(selectedKeys, confirm)}
            icon="search"
            size="small"
            style={{ width: 90, marginRight: 8 }}
          >
            Search
          </Button>
          <Button
            onClick={() => this.handleReset(clearFilters)}
            size="small"
            style={{ width: 90 }}
          >
            Reset
          </Button>
        </div>
      ),
      filterIcon: filtered => <Icon type="search" style={{ color: filtered ? '#1890ff' : undefined }} />,
      onFilter: (value, record) =>
      record[dataIndex]
        ? record[dataIndex]
            .toString()
            .toLowerCase()
            .includes(value.toLowerCase())
        : false,
      onFilterDropdownVisibleChange: (visible) => {
        if (visible) {
          setTimeout(() => this.searchInput.select());
        }
      }
    })

    handleChange(pagination, filters, sorter){
      console.log('Various parameters', pagination, filters, sorter);
      this.setState({
        filteredInfo: filters,
        sortedInfo: sorter,
      });
    }

    clearFilters(){
      this.setState({ filteredInfo: null });
    }

    clearAll(){
      this.setState({
        filteredInfo: null,
        sortedInfo: null,
      });
    }

    fetchData = () => {
        adalApiFetch(fetch, "/PageTemplates", {})
          .then(response => response.json())
          .then(responseJson => {
            if (!this.isCancelled) {
                const results= responseJson.map(row => ({
                    key: row.Id,
                    Name: row.Name,
                    SiteType: row.SiteType,
                    Tags: row.Tags
                  }))
              this.setState({ data: results });
            }
          })
          .catch(error => {
            console.error(error);
          });
      };


    componentDidMount(){
        this.fetchData();
    }

    render(){
          let { sortedInfo, filteredInfo } = this.state;
        sortedInfo = sortedInfo || {};
        filteredInfo = filteredInfo || {};

        const columns = [
                {
                    title: 'Id',
                    dataIndex: 'key',
                    key: 'key',
                }, 
                {
                    title: 'Name',
                    dataIndex: 'Name',
                    key: 'Name',
                }, 
                {
                    title: 'Site Type',
                    dataIndex: 'SiteType',
                    key: 'SiteType',
                    filters: [
                      { text: 'Modern Team Site', value: 'Modern Team Site' },
                      { text: 'CommunicationSite', value: 'CommunicationSite' },
                    ],
                    filteredValue: filteredInfo.SiteType || null,
                    onFilter: (value, record) => record.SiteType.includes(value),
                },{
                  title: 'Tags',
                  key: 'Tags',
                  dataIndex: 'Tags',
                  ...this.getColumnSearchProps('Tags'),
                  render: Tags => (
                    <span>
                    {Tags && Tags.map(tag => {
                      let color = tag.length > 5 ? 'geekblue' : 'green';
                      if (tag === 'loser') {
                        color = 'volcano';
                      }
                      return <Tag color={color} key={tag}>{tag.toUpperCase()}</Tag>;
                    })}
                  </span>)

                }
        ];

        const rowSelection = {
            selectedRowKeys: this.props.selectedRows,
            onChange: (selectedRowKeys) => {
              this.props.onRowSelect(selectedRowKeys);
            }
          };


        return (
          <div>
            <Button onClick={this.clearFilters}>Clear filters</Button>
            <Button onClick={this.clearAll}>Clear filters and sorters</Button>
            <Table rowSelection={rowSelection}  columns={columns} dataSource={this.state.data} onChange={this.handleChange} />
          </div>
        );
    }
}

export default ListPageTemplatesWithSelection;

然而,当我添加这一行:...this.get列搜索道具('Tags'),

然后我得到这个错误

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
▶ 23 stack frames were collapsed.
AsyncFunc._callee$
src/helpers/AsyncFunc.js:26
  23 | const { default: Component } = await importComponent();
  24 | Nprogress.done();
  25 | if (this.mounted) {
> 26 |   this.setState({
  27 |     component: <Component {...this.props} />
  28 |   });
  29 | }

更新2

这是容器组件

import React, { Component } from 'react';
import { Input} from 'antd';
import Form from '../../components/uielements/form';
import Button from '../../components/uielements/button';
import Notification from '../../components/notification';
import { adalApiFetch } from '../../adalConfig';
import   ListPageTemplatesWithSelection  from './ListPageTemplatesWithSelection';

const FormItem = Form.Item;

class CreateCommunicationSiteCollectionForm extends Component {
    constructor(props) {
        super(props);
        this.state = {Title:'',Url:'', SiteDesign:'', Description:'',Owner:'',Lcid:'', PageTemplateIds : []};
        this.handleChangeTitle = this.handleChangeTitle.bind(this);
        this.handleValidationCommunicationSiteUrl = this.handleValidationCommunicationSiteUrl.bind(this);
        this.handleChangeCommunicationSiteUrl = this.handleChangeCommunicationSiteUrl.bind(this);
        this.handleChangeSiteDesign = this.handleChangeSiteDesign.bind(this);
        this.handleChangeDescription = this.handleChangeDescription.bind(this);
        this.handleChangeOwner = this.handleChangeOwner.bind(this);
        this.handleChangelcid = this.handleChangelcid.bind(this);

        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleRowSelect = this.handleRowSelect.bind(this);
    }

    handleRowSelect(ids) {
        this.setState({ PageTemplateIds: ids });
    }

    handleChangeTitle(event){
        this.setState({Title: event.target.value});
    }

    handleValidationCommunicationSiteUrl(rule, value, callback){
        const form = this.props.form;
        const str = form.getFieldValue('communicationsiteurl');        
        var re = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/i;
        if (str && !str.match(re)) {
            callback('Communication site url is not correctly formated.');
        } 
        else {
            callback();
        }
    }

    handleChangeCommunicationSiteUrl(event){
        this.setState({Url: event.target.value});
    }

    handleChangeSiteDesign(event){
        this.setState({SiteDesign: event.target.value});
    }

    handleChangeDescription(event){
        this.setState({Description: event.target.value});
    }

    handleChangeOwner(event){
        this.setState({Owner: event.target.value});
    }

    handleChangelcid(event){
        this.setState({Lcid: event.target.value});
    }

    handleSubmit(e){
        e.preventDefault();
        this.props.form.validateFieldsAndScroll((err, values) => {
            if (!err) {
                let data = new FormData();
                //Append files to form data
                //data.append(

                const options = {
                  method: 'post',
                  body: JSON.stringify(
                    {
                        "Title": this.state.Title,
                        "Url": this.state.Url, 
                        "SiteDesign": this.state.SiteDesign,
                        "Description": this.state.Description,
                        "Owner": this.state.Owner,
                        "Lcid": this.state.Lcid,
                        "PageTemplateIds": this.state.PageTemplateIds
                    }),
                    headers: {
                            'Content-Type': 'application/json; charset=utf-8'
                    }                    
                };

                adalApiFetch(fetch, "/SiteCollection/CreateCommunicationSite", options)
                  .then(response =>{
                    if(response.status === 201){
                        Notification(
                            'success',
                            'Communication Site created',
                            ''
                            );
                     }else{
                        throw "error";
                     }
                  })
                  .catch(error => {
                    Notification(
                        'error',
                        'Site collection not created',
                        error
                        );
                    console.error(error);
                });
            }
        });      
    }

    render() {
        const { getFieldDecorator } = this.props.form;
        const formItemLayout = {
        labelCol: {
            xs: { span: 24 },
            sm: { span: 6 },
        },
        wrapperCol: {
            xs: { span: 24 },
            sm: { span: 14 },
        },
        };
        const tailFormItemLayout = {
        wrapperCol: {
            xs: {
            span: 24,
            offset: 0,
            },
            sm: {
            span: 14,
            offset: 6,
            },
        },
        };
        return (
            <Form onSubmit={this.handleSubmit}>
                <FormItem {...formItemLayout} label="Title" hasFeedback>
                {getFieldDecorator('Title', {
                    rules: [
                        {
                            required: true,
                            message: 'Please input your communication site title',
                        }
                    ]
                })(<Input name="title" id="title" onChange={this.handleChangeTitle} />)}
                </FormItem>
                <FormItem {...formItemLayout} label="Communication Site Url" hasFeedback>
                {getFieldDecorator('communicationSiteUrl', {
                    rules: [
                        {
                            required: true,
                            message: 'CommunicationSite site collection url',
                        },
                        {
                            validator: this.handleValidationCommunicationSiteUrl
                        }
                    ]
                })(<Input name="communicationsSiteUrl" id="communicationsSiteUrl" onChange={this.handleChangeCommunicationSiteUrl} />)}
                </FormItem>
                <FormItem {...formItemLayout} label="Site Design" hasFeedback>
                {getFieldDecorator('sitedesign', {
                    rules: [
                        {
                            required: true,
                            message: 'Please input your site design',
                        }
                    ]
                })(<Input name="sitedesign" id="sitedesign" onChange={this.handleChangeSiteDesign} />)}
                </FormItem>
                <FormItem {...formItemLayout} label="Description" hasFeedback>
                {getFieldDecorator('description', {
                    rules: [
                        {
                            required: true,
                            message: 'Please input your description',
                        }
                    ],
                })(<Input name="description" id="description"  onChange={this.handleChangeDescription} />)}
                </FormItem>
                <FormItem {...formItemLayout} label="Owner" hasFeedback>
                {getFieldDecorator('owner', {
                    rules: [
                        {
                            required: true,
                            message: 'Please input your owner',
                        }
                    ],
                })(<Input name="owner" id="owner"  onChange={this.handleChangeOwner} />)}
                </FormItem>
                <FormItem {...formItemLayout} label="Lcid" hasFeedback>
                {getFieldDecorator('lcid', {
                    rules: [
                        {
                            required: true,
                            message: 'Please input your lcid',
                        }
                    ],
                })(<Input name="lcid" id="lcid"  onChange={this.handleChangelcid} />)}
                </FormItem>          

                <ListPageTemplatesWithSelection onRowSelect={this.handleRowSelect} selectedRows={this.state.PageTemplateIds}/>


                <FormItem {...tailFormItemLayout}>
                    <Button type="primary" htmlType="submit">
                        Create communication site
                    </Button>
                </FormItem>


            </Form>



        );
    }
}

const WrappedCreateCommunicationSiteCollectionForm = Form.create()(CreateCommunicationSiteCollectionForm);
export default WrappedCreateCommunicationSiteCollectionForm;

共有2个答案

满昊然
2023-03-14

正如在另一个线程中所说,如果您试图导入一个不存在的组件,则会出现此错误。确保您没有输入错误,并且组件确实以这种方式命名。对于库,请确保使用正确的版本,因为组件在不同的版本中可能具有不同的名称。

具有类似问题的链接:
未捕获错误:不变冲突:元素类型无效:应为字符串(用于内置组件)或类/函数,但得到:object
React。createElement:类型无效--应为字符串或类/函数,但Get:未定义

阎阳
2023-03-14

从您提供的错误中很难猜出哪里出了问题。所以我能做的就是指出一些你应该注意的事情。

getColumnSearchProps()的呈现方法错误。如果文本为null(由于某行没有任何标记),它将尝试将其转换为字符串并崩溃。为避免出现这种情况,请在渲染之前选中“文本存在”:

render: text =>
      text ? (
        <Highlighter
          highlightStyle={{ backgroundColor: "#ffc069", padding: 0 }}
          searchWords={[this.state.searchText]}
          autoEscape
          textToHighlight={text.toString()}
        />
      ) : null

这同样适用于过滤器上的onFilter方法:

onFilter: (value, record) =>
  record[dataIndex]
    ? record[dataIndex]
        .toString()
        .toLowerCase()
        .includes(value.toLowerCase())
    : false,

您有两个渲染标记列的方法。一个在getGonnSearchProps()内,一个在后...this.get的ColnSearchProps('Tags')调用。这应该没问题,因为后者将覆盖前一个。话说回来,如果你不需要,为什么要宣布珍贵呢?

希望这有帮助。

 类似资料:
  • 问题内容: 这就是我通常做,以确定输入是一个/ -但不是。因为很多时候我偶然发现了一个错误,即一个函数错误地传递了一个对象,而目标函数确实假设这实际上是一个or 。 我的问题是:是否有更好的方法来实现这一目标? 问题答案: 仅在python 2中(不是python 3): 实际上就是您想要的,否则您会错过很多像列表一样的东西,但它们不是or的子类。

  • 我正在学习如何使用Spring靴和胸腺嘧啶。我有一个问题,我在表单列表中提供一个特定对象的列表到一个Thymeleaf页面。当用户选择值并发布结果时,结果是所选对象的字符串,并且与我想要存储值的对象不兼容。 这可能听起来像一口,所以下面是代码。 输入:一个类将一组成分传递给表单,这个类在一个类成分列表中传递给表单(过滤对此无关紧要--插入一个列表作为model属性的值,键是一种成分类型) Thym

  • 问题内容: 基本上,我有一堆数据,其中第一列是字符串(标签),其余列是数值。我运行以下命令: 这样可以很好地读取大多数数据,但是label列只是获取“ nan”。我该如何处理? 问题答案: 默认情况下,使用:这就是将字符串列转换为NaN的原因,因为毕竟它们不是数字… 您可以使用以下方法来尝试猜测列的实际类型: 您可以使用它们的名称访问列,例如… 如果您不知道列应该是什么,那么使用是一个好技巧。如果

  • 问题内容: 我正在使用 Python 2 从 ASCII编码的 文本文件中解析JSON 。 当使用或 加载这些文件时,我所有的字符串值都转换为Unicode对象而不是字符串对象。问题是,我必须将数据与仅接受字符串对象的某些库一起使用。我 无法更改库, 也 无法 更新它们。 是否可以获取字符串对象而不是Unicode对象? 更新资料 很久以前 ,当我坚持使用 Python 2 时就问 了 这个问题。

  • 问题内容: 我知道这听起来微不足道,但是我没有意识到 的功能很奇怪。我有一个实际上是字符串形式的“数字”列表,因此我先将它们转换为整数,然后尝试进行排序。 给我: 我想要的是 我四处寻找与排序数字集相关的算法,但是我发现所有算法都涉及对字母数字集进行排序。 我知道这可能是个没有脑子的问题,但是google和我的教科书没有提供比该.sort()功能有用的功能。 问题答案: 您实际上尚未将字符串转换为

  • 问题内容: 样本数据: 我使用以下查询将’ ‘’分隔的字符串分成几行: 我的查询存在问题,我不想为每个拆分的电子邮件地址创建新行-我想为其添加新列。 email_address列中最多有3个单独的电子邮件地址。有什么建议?如果它的大小超过3,最好是答案可以占n列。 问题答案: 测试数据 询问 结果