尝试基于输入来筛选一个数组。

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

Trying to filter an array based on inputs

问题

我已经实现了类型的筛选功能。我创建了一个名为documentTypes的JSON文件,其中存储了文档可能具有的不同类型的值。我有一个Vue输入字段,与一个名为filteredDocumentType的空变量双向绑定。对于我的输入选项,它循环遍历包含不同文档类型的JSON文件。

<b-form-group class="mt-4">
    <b-form-select v-model="filteredDocumentType">
        <template>
            <b-form-select-option :value="null" disabled>-- 选择文档类型 --</b-form-select-option>
        </template>
        <b-form-select-option :value="'all'">-- 所有 --</b-form-select-option>
        <option v-for="documentType in documentTypes" :key="documentType" :value="documentType">
            {{ $t('model.document.types.' + documentType) }}
        </option>
    </b-form-select>
</b-form-group>

然后,我创建了一个计算属性,它获取文档数组并检查输入和类型。如果没有选择类型或用户选择"all",则将显示列表中的所有文档,但如果有可用类型并且用户选择了一个类型,那么列表将被过滤以仅显示具有特定类型的文档。

filteredDocuments() {
    if (this.filteredDocumentType === null || this.filteredDocumentType === 'all') {
        return (this.documents ?? []).filter(document =>
            (document.name.toUpperCase().includes(this.search.toUpperCase()) ||
            this.$t(`model.document.types.${document.type}`).toUpperCase().includes(this.search.toUpperCase()))
        );
    } else {
        return (this.documents ?? []).filter(document =>
            (document.name.toUpperCase().includes(this.search.toUpperCase()) ||
            this.$t(`model.document.documentTypes.${document.type}`).toUpperCase().includes(this.search.toUpperCase())) &&
            document.type === this.filteredDocumentType
        );
    }
}

这部分已经完成,现在我想为标签执行类似的操作。但是,我没有在JSON文件中存储标签,因为它们由用户在前端的不同位置输入。如果我创建一个名为documentTags的JSON文件,并手动将用户标签添加到列表中,然后导入它,我可以使用相同的方法。

<b-form-group class="mt-4">
    <w-b-form-select v-model="filteredDocumentType">
        <template>
            <b-form-select-option :value="null" disabled>-- 选择文档标签 --</b-form-select-option>
        </template>
        <b-form-select-option :value="'all'">({{ $t('all') }})</b-form-select-option>
        <option v-for="documentTag in documentTags" :key="documentTag" :value="documentTag">
            {{ documentTag }}
        </option>
    </w-b-form-select>
</b-form-group>

但是,如果我不想使用JSON文件,我需要循环遍历嵌套的标签数组,并确保过滤掉任何带有空标签的文档,以确保不会获得空白的输入字段。

以下方法不起作用:

<option v-for="documentTag in documents.tags" :key="documentTag" :value="documentTag">
    {{ documentTag }}
</option>

我也尝试过这种方式:

<option v-for="documentTag in document.tags[0]" :key="documentTag" :value="documentTag">
    {{ documentTag }}
</option>

要循环遍历标签,您应该使用嵌套的循环。在Vue模板中,您可以使用v-for指令来完成这项任务。以下是一个示例代码段,用于循环遍历文档数组以获取标签:

<b-form-group class="mt-4">
    <w-b-form-select v-model="filteredDocumentTag">
        <template>
            <b-form-select-option :value="null" disabled>-- 选择文档标签 --</b-form-select-option>
        </template>
        <b-form-select-option :value="'all'">({{ $t('all') }})</b-form-select-option>
        <template v-for="document in documents">
            <option v-for="tag in document.tags" :key="tag" :value="tag">
                {{ tag }}
            </option>
        </template>
    </w-b-form-select>
</b-form-group>

这将循环遍历文档数组中的每个文档,并为每个文档中的标签创建选项。这样,用户可以选择文档标签以进行过滤。请确保在Vue组件中设置filteredDocumentTag以便与选择的标签进行绑定。

英文:

I have an array of documents with different values.
Here is a simplified example:

documents: [
 {
    name: &#39;Some name&#39;,
    type: &#39;PDF&#39;,
    tags: [
        &#39;tag 1&#39;,
        &#39;tag 2&#39;,
        &#39;tag 3&#39;
    ],
    dateOfCreation: &#39;DD/MM&#39;
  },
  {
    name: &#39;Some name&#39;,
    type: &#39;Excel&#39;,
    tags: [
        &#39;tag 4&#39;,
    ],
    dateOfCreation: &#39;DD/MM&#39;
  },
  {
    name: &#39;Some name&#39;,
    type: &#39;Word&#39;,
    tags: &#39;&#39;,
    dateOfCreation: &#39;DD/MM&#39;
  }
]

I am creating two input fields. One has a dropdown displaying the types of documents and the other is a dropdown that display the tags of each document.
My goal is that when the user selects a type or tag from the dropdown, the documents array will be filtered to only show the documents with that specific type or tag.

I already accomplished this with the types.

I made a json file called documentTypes where I store the different type values that the document can have.

[
  &quot;pdf&quot;,
  &quot;word&quot;,
  &quot;excel&quot;
]

I have a vue input field, which has a two-way-binding with an empty variable called filteredDocumentType.
For my input options it loops through the json file that contain the different document types.

  &lt;b-form-group class=&quot;mt-4&quot;&gt;
    &lt;b-form-select v-model=&quot;filteredDocumentType&quot;&gt;

      &lt;template&gt;
        &lt;b-form-select-option :value=&quot;null&quot; disabled&gt;-- &#39;Select document by type&#39; --&lt;/b-form-   select-option&gt;
      &lt;/template&gt;

      &lt;b-form-select-option :value=&quot;&#39;all&#39;&quot;&gt;-- All --&lt;/b-form-select-option&gt;

      &lt;option v-for=&quot;documentType in documentTypes&quot; :key=&quot;documentType&quot; :value=&quot;documentType&quot;&gt;
        {{ $t(&#39;model.document.types.&#39; + documentType) }}
      &lt;/option&gt;

    &lt;/b-form-select&gt;
  &lt;/b-form-group&gt;

Then I make a computed property that gets the documents array and checks the input and type. If no type has been selected or if the user selects "all" then all documents will be shown in the list, but if there are types available and the user picks one, then the list will get filtered to show only that specific type of document.

      filteredDocuments() {
        if (this.filteredDocumentType === null || this.filteredDocumentType === &#39;all&#39;) {
          return (this.documents ?? []).filter(document =&gt;
            (document.name.toUpperCase().includes(this.search.toUpperCase()) ||
                 this.$t(`model.document.types.${document.type}`).toUpperCase().includes(this.search.toUpperCase())))
    }
        else {
          return (this.documents ?? []).filter(document =&gt;
            (document.name.toUpperCase().includes(this.search.toUpperCase()) ||
               this.$t(`model.document.documentTypes.${document.type}`).toUpperCase().includes(this.search.toUpperCase())) &amp;&amp;
        document.type === this.filteredDocumentType)
        }

This works, but I want to do the same thing for the tags. But I do not store my tags in a json file. As you can see in the array, each document can have a multiple set of tags, and I cannot make a json file for them, because they get entered by the user on a different place on the frontend.

If I create a json file called documentTags and manually add the user-tags in a list and then import it, then I can use the same method:

  filteredDocuments() {
    if (this.filteredDocumentType === null || this.filteredDocumentType === &#39;all&#39;) {
      return (this.documents ?? []).filter(document =&gt;
        (document.name.toUpperCase().includes(this.search.toUpperCase()) ||
             document.tags[0].toUpperCase().includes(this.search.toUpperCase())))
}
    else {
      return (this.documents ?? []).filter(document =&gt;
        (document.name.toUpperCase().includes(this.search.toUpperCase()) ||
           document.tags[0].toUpperCase().includes(this.search.toUpperCase())) &amp;&amp;
    document.tags[0] === this.filteredDocumentType)
    }

and

      &lt;b-form-group class=&quot;mt-4&quot;&gt;
        &lt;w-b-form-select v-model=&quot;filteredDocumentType&quot;&gt;

          &lt;template&gt;
            &lt;b-form-select-option :value=&quot;null&quot; disabled&gt;-- {{ 
    $t(&#39;selectDocumentByType&#39;) }} --&lt;/b-form-select-option&gt;
          &lt;/template&gt;

          &lt;b-form-select-option :value=&quot;&#39;all&#39;&quot;&gt;({{ $t(&#39;all&#39;) }})&lt;/b- 
   form-select-option&gt;

          &lt;option v-for=&quot;documentTag in documentTags&quot; 
    :key=&quot;documentTag&quot; :value=&quot;documentTag&quot;&gt;
            {{ documentTag }}
          &lt;/option&gt;

        &lt;/w-b-form-select&gt;
      &lt;/b-form-group&gt;

But what do I loop through if I don't want to use a json file?
I need somehow loop through the nested array containing tags and also make sure to filter out any document with empty tags to make sure I do not get blank input fields.

The following method does not work:

  &lt;option v-for=&quot;documentTag in documents.tags&quot; :key=&quot;documentTag&quot; :value=&quot;documentTag&quot;&gt;
    {{ documentTag }}
  &lt;/option&gt;

Also tried this:

  &lt;option v-for=&quot;documentTag in document.tags[0]&quot; :key=&quot;documentTag&quot; :value=&quot;documentTag&quot;&gt;
    {{ documentTag }}
  &lt;/option&gt;

答案1

得分: 0

我建议使用计算属性来存储标签列表

这将由Vue计算,每当 "documents" 发生更改时。

computed: {

    uniqueTags(){
        const uniqueTagsSoFar = [];
        this.documents.forEach(document => {
            if (document && document.tags && document.tags.length > 0){
                document.tags.forEach(tag => {
                    if (!uniqueTagsSoFar.includes(tag)){
                        uniqueTagsSoFar.push(tag)
                    }
                })
            }
        });
        return uniqueTagsSoFar
    }

}

然后,在你的程序中,将 this.uniqueTags 视为变量。它将是一个标签列表,不包括空字符串,并且每个标签只列出一次。

英文:

I suggest using a Computed Property to store the list of tags

This will be calculated by Vue, every time "documents" changes.

computed: {

    uniqueTags(){
        const uniqueTagsSoFar = [];
        this.documents.forEach(document =&gt; {
            if (document &amp;&amp; document.tags &amp;&amp; document.tags.length&gt;0){
                document.tags.forEach(tag=&gt;{
                    if (!uniqueTagsSoFar.includes(tag)){
                        tags.push(tag)
                    }
                })
            }
        });
        return uniqueTagsSoFar
    }

}

Then, in your program, treat this.uniqueTags like a variable. It will be a list of tags, not including "", and listing each tag only once.

答案2

得分: 0

获取计算属性中的标签的一种方法:

const documents = [
  {
    name: 'Some name',
    type: 'PDF',
    tags: [
      'tag 1',
      'tag 2',
      'tag 3'
    ],
    dateOfCreation: 'DD/MM'
  },
  {
    name: 'Some name',
    type: 'Excel',
    tags: [
      'tag 4',
      'tag 1',
      'tag 3'
    ],
    dateOfCreation: 'DD/MM'
  },
  {
    name: 'Some name',
    type: 'Word',
    tags: '',
    dateOfCreation: 'DD/MM'
  }
]

const tags = documents.reduce((r, s) => {
  if (s.tags.length) r.push(s.tags)
  return r;
}, []).flat()

console.log([...new Set(tags)])

这段代码用于从给定的documents数组中提取标签,并去除重复项。

英文:

One way for getting tags in computed property:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const documents = [
 {
    name: &#39;Some name&#39;,
    type: &#39;PDF&#39;,
    tags: [
        &#39;tag 1&#39;,
        &#39;tag 2&#39;,
        &#39;tag 3&#39;
    ],
    dateOfCreation: &#39;DD/MM&#39;
  },
  {
    name: &#39;Some name&#39;,
    type: &#39;Excel&#39;,
    tags: [
        &#39;tag 4&#39;,
        &#39;tag 1&#39;,
        &#39;tag 3&#39;    ],
    dateOfCreation: &#39;DD/MM&#39;
  },
  {
    name: &#39;Some name&#39;,
    type: &#39;Word&#39;,
    tags: &#39;&#39;,
    dateOfCreation: &#39;DD/MM&#39;
  }
]
const tags = documents.reduce((r,s) =&gt; {
  if (s.tags.length) r.push(s.tags)
  return r;
}, []).flat()
console.log([...new Set(tags)])

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年2月27日 01:18:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75573725.html
匿名

发表评论

匿名网友

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

确定