# TagsWidget

**Category:** Features/Enrich/Tags

## Overview

### Introduction

The `TagsWidget` component enhances the entity page by displaying the tags that are associated with the entity. It also enables to add new tags to the entity, and remove existing tags from it.

The assigned tags are being immediately saved after added/removed from the entity, without the need to click on a CTA.

Wix Patterns is responsible for interacting with the tags management service for adding, removing and updating tags. The vertical is responsible for interacting with its api for assign and unassign tags to the entity on the `onSubmit` callback.


  



### Getting Started

1. Wrap your app with one of the Wix Patterns providers: [WixPatternsProvider](./?path=/story/base-components-providers--wixpatternsprovider).

2. Wrap your page with [WidgetsFormProvider](./?path=/story/base-components-providers--widgetsformprovider).

```diff
+ import { WidgetsFormProvider } from '@wix/patterns/page';

export const MyPageProvider = ({ children }) => {

  return (
+   
      
+   
  );
};
```

3. Add `TagsWidget` to one of your child components and pass the `initialTags` prop to it from the `entity` object, `entityTypeName` and an `onSubmit` callback to call the entity api with the updated tags.

```diff
  import { Page } from '@wix/design-system'';
  import { MyEntityCard } from '../components/MyEntityCard';
- import { MyEntity } from '@wix/ambassador-v1-entity/types';
+ import { MyEntity, Tags, UpdateEntityRequest } from '@wix/ambassador-v1-entity/types';
+ import { UpdateEntity } from '@wix/ambassador-v1-entity/http';
+ import { TagsWidget } from '@wix/patterns';

function MyEntityPage({ entity }: { entity: MyEntity }) {

+   const handleTagsSubmit = async(tags: Tags) => {
+     const updatedEntity: UpdateEntityRequest = {
+       ...entity,
+       tags,
+     };
+
+      await httpClient.request(updateEntity(updatedEntity))
+   };

    return (
       
          
          
            
              
                
              
+             
+               
+             
            
          
        
    );
  }
```

4. In the previous step implementation, the tags will be updated in the server on every action of assign or unassign a tag. If you want to update the tags only on submit of a button, you can use the `TagsWidget` without the `onSubmit` prop and use the updated value of the tags from the `state` object returned from the [useWidgetsFormContext](./?path=/story/common-hooks--usewidgetsformcontext) hook.

```diff
- import { Page } from '@wix/design-system'';
+ import { Page, Button } from '@wix/design-system'';
  import { MyEntityCard } from '../components/MyEntityCard';
  import { MyEntity, Tags, UpdateEntityRequest } from '@wix/ambassador-v1-entity/types';
  import { UpdateEntity } from '@wix/ambassador-v1-entity/http';
- import { TagsWidget } from '@wix/patterns';
+ import { TagsWidget, useWidgetsFormContext, useSelector } from '@wix/patterns';

function MyEntityPage({ entity }: { entity: MyEntity }) {

+   const state = useWidgetsFormContext();
+   const isDirty = useSelector(() => state.isDirty);

    const handleTagsSubmit = async(tags: Tags) => {
     const updatedEntity: UpdateEntityRequest = {
        ...entity,
        tags,
      };

      await httpClient.request(updateEntity(updatedEntity))
   };

    return (
       
-         
+          {
+                  const { isValid, data } = await state.validate();
+                  if (data.tags) {
+                    await handleTagsSubmit(data.tags);
+                  }
+                }}
+              >
+                Save
+              
+            }
+          />
          
            
              
                
              
              
                
              
            
          
        
    );
  }
```


## Examples

### Immediate updates

Tags are being updated on every assign / unassign.

```tsx
/* eslint-disable */

import React from 'react';
import { TagsWidget } from '@wix/patterns';
import { Cell, Layout, Page, Card, Text } from '@wix/design-system';
import {
  DummyEntity,
  Tags,
} from '@wix/ambassador-cairo-dummyservice-v1-dummy-entity/types';

function Basic() {
  const demoEntity: DummyEntity = {
    id: 'id',
    name: 'Hello world!',
    tags: { privateTags: { tagIds: ['1','2'] } },
  };

  const handleSubmit = ({ allTags } : { allTags: Tags }) => {
    console.log('Updated assigned tags: ' + allTags.privateTags?.tagIds);
  };

  return (
    <Page height="500px">
      <Page.Header title="My Entity Page" />
      <Page.Content>
        <Layout>
          <Cell span={8}>
            <Card>
              <Card.Header title="Name" />
              <Card.Divider />
              <Card.Content>
                <Text>{demoEntity.name}</Text>
              </Card.Content>
            </Card>
          </Cell>
          <Cell span={4}>
            <TagsWidget
              fqdn="wix.patterns.dummyservice.v1.dummy_entity"
              entityTypeName="Demo Entity"
              entityId={demoEntity.id}
              initialTags={demoEntity.tags}
              onSubmit={handleSubmit}
            />
          </Cell>
        </Layout>
      </Page.Content>
    </Page>
  );
}
```

---

### Deferred updates

Update tags on button click.

```tsx
/* eslint-disable */

import React from 'react';
import { TagsWidget } from '@wix/patterns';
import { Cell, Layout, Page, Card, Text, Button } from '@wix/design-system';
import { DummyEntity } from '@wix/ambassador-cairo-dummyservice-v1-dummy-entity/types';

function UpdateOnDemand() {
  const demoEntity: DummyEntity = {
    id: 'id',
    name: 'Hello world!',
    tags: { privateTags: { tagIds: ['1','2'] } },
  };

  const handleSubmit = () => {
    console.log('Updated assigned tags');
  };

  return (
    <Page height="500px">
      <Page.Header
        title="My Entity Page"
        actionsBar={
          <Button
            onClick={async () => {
              await handleSubmit();
            }}
          >
            Save
          </Button>
        }
      />
      <Page.Content>
        <Layout>
          <Cell span={8}>
            <Card>
              <Card.Header title="Name" />
              <Card.Divider />
              <Card.Content>
                <Text>{demoEntity.name}</Text>
              </Card.Content>
            </Card>
          </Cell>
          <Cell span={4}>
            <TagsWidget
              fqdn="wix.patterns.dummyservice.v1.dummy_entity"
              entityTypeName="Demo Entity"
              entityId={demoEntity.id}
              initialTags={demoEntity.tags}
            />
          </Cell>
        </Layout>
      </Page.Content>
    </Page>
  );
}
```

---

### External state

Initial the state by yourself and not be connected to entity page. In this use case you won't need to wrap your code with the provider `WidgetsFormProvider`

```tsx
/* eslint-disable */
import React from 'react';
import { TagsWidget, useTagsWidget } from '@wix/patterns';
import { DummyEntity } from '@wix/ambassador-cairo-dummyservice-v1-dummy-entity/types';

function ReadOnly() {
  const demoEntity: DummyEntity = {
    id: 'id',
    name: 'Hello world!',
    tags: { privateTags: { tagIds: ['1','2'] } },
  };

  const handleSubmit = () => {
    console.log('Updated assigned tags');
  };

  const state = useTagsWidget({
    fqdn: 'wix.patterns.dummyservice.v1.dummy_entity',
  });


  return (
    <TagsWidget
      entityTypeName="Demo Entity"
      entityId={demoEntity.id}
      initialTags={demoEntity.tags}
      onSubmit={handleSubmit}
      state={state}
    />
  );
}
```

---

### Inline theme

In inline theme, the content will not be inside a card.

```tsx
/* eslint-disable */
import React from 'react';
import { TagsWidget, useTagsWidget } from '@wix/patterns';
import { DummyEntity } from '@wix/ambassador-cairo-dummyservice-v1-dummy-entity/types';

function Inline() {
  const demoEntity: DummyEntity = {
    id: 'id',
    name: 'Hello world!',
    tags: { privateTags: { tagIds: ['1','2'] } },
  };

  const handleSubmit = () => {
    console.log('Updated assigned tags');
  };

  const state = useTagsWidget({
    fqdn: 'wix.patterns.dummyservice.v1.dummy_entity',
  });

  
  return (
    <TagsWidget
      state={state}
      entityTypeName="Demo Entity"
      entityId={demoEntity.id}
      initialTags={demoEntity.tags}
      onSubmit={handleSubmit}
      theme='inline'
    />
  );
}
```

---

### Read only mode

Show the tags without option to edit them.

```tsx
/* eslint-disable */
import React from 'react';
import { TagsWidget, useTagsWidget } from '@wix/patterns';
import { DummyEntity } from '@wix/ambassador-cairo-dummyservice-v1-dummy-entity/types';

function ReadOnly() {
  const demoEntity: DummyEntity = {
    id: 'id',
    name: 'Hello world!',
    tags: { privateTags: { tagIds: ['1','2'] } },
  };

  const handleSubmit = () => {
    console.log('Updated assigned tags');
  };

  const state = useTagsWidget({
    fqdn: 'wix.patterns.dummyservice.v1.dummy_entity',
  });


  return (
      <TagsWidget
        entityTypeName="Demo Entity"
        entityId={demoEntity.id}
        initialTags={demoEntity.tags}
        state={state}
        onSubmit={handleSubmit}
        readOnly
      />
  );
}
```

## API

### Props

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `fqdn` | `string` | No | - | The FQDN of the entity. The FQDN used to extract the schema from the data-extension service. The FQDN should not be provided if `state` is specified. |
| `entityTypeName` | `string` | Yes | - | A string that represents the name of the entity type (e.g., "Orders"), displayed as the title of the manage tags modal. |
| `entityId` | `string \| null` | No | - | A string that represents the ID of the current entity. |
| `initialTags` | `Tags` | No | - | Tags object associated with the entity when the widget is loaded. |
| `subtitle` | `string` | No | - | A subtitle to show on the tags widget card. Relevant for the default card theme only. |
| `dataHook` | `string` | No | - | Applies a `data-hook` HTML attribute that can be used in tests. |
| `onSubmit` | `OnSubmitTagsFuncType` | No | - | A callback function that is called when a user adds or removes tags from the entity. @param tags - An object containing: `allTags`: The updated tags object containing both private and public tags. \ `addedTags`: An array of added tags. \ `removedTags`: An array of removed tags. |
| `origin` | `string` | No | - | The origin of the widget. |
| `theme` | `"inline" \| "card"` | No | - | The theme of the tags widget. |
| `readOnly` | `boolean` | No | - | Displays tags without the option to edit them. |
| `popoverProps` | `PopoverCommonProps` | No | - | Props to pass to the MultiSelect popover. |
| `manageTagsShowUndoToast` | `boolean` | No | - | When set to false, will hide the undo toast after renaming or deleting a tag in the manage tags modal. Defaults to true. |
| `state` | `TagsWidgetState` | No | - | The widget state (should not be used when `fqdn` is provided). The widget state (should be used when `fqdn` is not provided). |

## BI

### Tags Events

| Event                                                                                                     | Description                                                        |
| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| [144:171](https://bo.wix.com/data-tools/bi-catalog-app/event/144:171) | Send when a Tags' widget is loaded. Relevant for Verticals who allow use tags in their tables. |
| [144:172](https://bo.wix.com/data-tools/bi-catalog-app/event/144:172) | Send when a user click on the widget's ctas (not including assigning tag). Relevant for Verticals who allow use tags in their tables. |
| [144:173](https://bo.wix.com/data-tools/bi-catalog-app/event/144:173) | Send when a user assign or remove a tag from an item. Relevant for Verticals who allow use tags in their tables.|



### Component load events
Event   |   Description   |
--------- | --------------- |
[144:110](https://bo.wix.com/data-tools/bi-catalog-app/event/144:110) | Sent when a Wix Patterns component starts loading
[144:111](https://bo.wix.com/data-tools/bi-catalog-app/event/144:111) | Sent when a Wix Patterns component is done loading


#### 🐪 Couldn't find what you need?
* Check our [BI Catalog](https://bo.wix.com/data-tools/bi-catalog-app?viewId=all-items-view&selectedColumns=src%2Cevid%2Cname%2Cowner%2Cproduct%2CuserType+false%2CdateUpdated%2CdateCreated+false%2CcreatedBy+false%2Cstatus&source=%5B%7B%22id%22%3A%22144%22%2C%22name%22%3A%22144+-+Cairo%22%7D%5D)
* Contact us on [#cairo-bi](https://wix.slack.com/archives/C03N53KURH9)


