From b546420ed0cacba659212d53dc3deb6bc388fc06 Mon Sep 17 00:00:00 2001 From: jyash97 Date: Tue, 9 Apr 2019 21:52:55 +0530 Subject: [PATCH 1/3] Add ReactiveComponent without children in base Components --- content/docs/advanced/React.md | 2 +- content/docs/advanced/ReactiveComponent.md | 8 +- content/docs/advanced/SSR.md | 2 +- content/docs/advanced/nav.yml | 12 +-- .../docs/base-components/ReactiveComponent.md | 83 +++++++++++++++++++ .../docs/base-components/SelectedFilters.md | 4 +- content/docs/base-components/nav.yml | 17 ++++ 7 files changed, 114 insertions(+), 14 deletions(-) create mode 100644 content/docs/base-components/ReactiveComponent.md diff --git a/content/docs/advanced/React.md b/content/docs/advanced/React.md index 3323ffab5..0bc187a5d 100644 --- a/content/docs/advanced/React.md +++ b/content/docs/advanced/React.md @@ -6,7 +6,7 @@ sectionid: docs permalink: advanced/react.html prev: advanced/customquery.html prevTitle: "Defining Custom Queries" -next: advanced/reactivecomponent.html +next: advanced/reactivecomponentindepth.html nextTitle: "Reactive Component" redirect_from: - 'advanced/react' diff --git a/content/docs/advanced/ReactiveComponent.md b/content/docs/advanced/ReactiveComponent.md index 3e61982c0..a7c47afa6 100644 --- a/content/docs/advanced/ReactiveComponent.md +++ b/content/docs/advanced/ReactiveComponent.md @@ -1,16 +1,16 @@ --- -id: reactivecomponent +id: reactivecomponentindepth title: "Reactive Component" layout: docs sectionid: reactivecomponent -permalink: advanced/reactivecomponent.html +permalink: advanced/reactivecomponentindepth.html prev: react.html prevTitle: "React Prop" next: ssr.html nextTitle: "Server Side Rendering" redirect_from: - - "advanced/reactivecomponent" - - "reactivecomponent" + - "advanced/reactivecomponentindepth" + - "reactivecomponentindepth" --- We have built this library keeping you, the developer, in mind. If you're here, it is obvious that you want to create a custom component that is reactive in nature. Perhaps, you already have a component in your design kit and want it to work seamlessly with Reactivesearch. diff --git a/content/docs/advanced/SSR.md b/content/docs/advanced/SSR.md index 90b94226e..b8c5ea16d 100644 --- a/content/docs/advanced/SSR.md +++ b/content/docs/advanced/SSR.md @@ -4,7 +4,7 @@ title: "Server Side Rendering" layout: docs sectionid: docs permalink: advanced/ssr.html -prev: reactivecomponent.html +prev: reactivecomponentindepth.html prevTitle: "Reactive Component" next: componentsusage.html nextTitle: "Components Usage" diff --git a/content/docs/advanced/nav.yml b/content/docs/advanced/nav.yml index b590268d1..f3dee901c 100644 --- a/content/docs/advanced/nav.yml +++ b/content/docs/advanced/nav.yml @@ -59,26 +59,26 @@ title: Props href: /advanced/react.html#props forceInternal: true - - id: reactivecomponent + - id: reactivecomponentindepth title: Reactive Component - href: /advanced/reactivecomponent.html + href: /advanced/reactivecomponentindepth.html forceInternal: true subitems: - id: usage-with-defaultquery title: Usage with defaultQuery - href: /advanced/reactivecomponent.html#usage-with-defaultquery + href: /advanced/reactivecomponentindepth.html#usage-with-defaultquery forceInternal: true - id: usage-with-customquery title: Usage with customQuery - href: /advanced/reactivecomponent.html#usage-with-customquery + href: /advanced/reactivecomponentindepth.html#usage-with-customquery forceInternal: true - id: props title: Props - href: /advanced/reactivecomponent.html#props + href: /advanced/reactivecomponentindepth.html#props forceInternal: true - id: examples title: Examples - href: /advanced/reactivecomponent.html#examples + href: /advanced/reactivecomponentindepth.html#examples forceInternal: true - id: ssr title: Server Side Rendering diff --git a/content/docs/base-components/ReactiveComponent.md b/content/docs/base-components/ReactiveComponent.md new file mode 100644 index 000000000..0144754c2 --- /dev/null +++ b/content/docs/base-components/ReactiveComponent.md @@ -0,0 +1,83 @@ +--- +id: reactivecomponent +title: "Reactive Component" +layout: docs +sectionid: reactivecomponent +permalink: base-components/reactivecomponent.html +prev: selectedfilters.html +prevTitle: "SelectedFilters" +next: /list-components/singlelist.html +nextTitle: "List Components: SingleList" +redirect_from: + - 'basic-components/reactivecomponent.html' + - 'base-components/reactivecomponent' + - 'reactivecomponent' +--- + + +With `ReactiveComponent`, you can convert any React Component into a Reactivesearch component i.e. your react component will be able to talk to other Reactivesearch components and connect with your elasticsearch cluster seamlessly. `Note` This page only cover `ReactiveComponent` with `customQuery`. Read more [here](/advanced/reactivecomponentindepth.html). + +> How does this work? +> +> `ReactiveComponent` is a wrapper component that allows you to connect custom component(s) (passed as children) with the Reactivesearch ecosystem. + + +### Usage + +Let's suppose - we are building an e-commerce store for cars which displays a list of cars of a particular brand on their separate page as `example.com/cars/nissan`. Now, we want all the filters on that page (like pricing, type of car, model, year, etc) to only show the data relevant to the given brand (i.e. `nissan`). In this case, `ReactiveComponent` can be used with `customQuery` to achieve the desired behavior easily. + +We can then use the given ReactiveComponent to be watched by all the filters (via `react` prop) to avail the desired brand based filtering for all the filters. + +Check demo [here](https://codesandbox.io/s/3ylrrr0r5q). + + +```js + ({ + query: { + term: { + "brand.keyword": "Ford" + } + } + }) + } +/> +``` + + +### Props + +- **className** `String` + CSS class to be injected on the component container. +- **style** `Object` + CSS styles to be applied to the **DataSearch** component. +- **customQuery** `Function` + **returns** the custom query to be applied to the component, as defined in Elasticsearch Query DSL. + Custom query can be used to change the component's behavior for its subscribers. +- **onQueryChange** `Function` + is a callback function which accepts component's **prevQuery** and **nextQuery** as parameters. It is called everytime the component's query changes. This prop is handy in cases where you want to generate a side-effect whenever the component's query would change. +- **onAllData** `Function` + callback function which provides `hits` and `aggregations` as function params. +- **react** `Object` + `react` prop is available in components whose data view should reactively update when on or more dependent components change their states, e.g. [`ReactiveMap`](/map-components/reactivemap.html), [`ReactiveList`](/basic-components/reactivelist.html). + - **key** `String` + one of `and`, `or`, `not` defines the combining clause. + - **and** clause implies that the results will be filtered by matches from **all** of the associated component states. + - **or** clause implies that the results will be filtered by matches from **at least one** of the associated component states. + - **not** clause implies that the results will be filtered by an **inverse** match of the associated component states. + - **value** `String or Array or Object` + - `String` is used for specifying a single component by its `componentId`. + - `Array` is used for specifying multiple components by their `componentId`. + - `Object` is used for nesting other key clauses. + +- **URLParams** `Boolean` [optional] + enable creating a URL query string parameter based on the selected value of the list. This is useful for sharing URLs with the component state. Defaults to `false`. + +### Demo + + + +See storybook for ReactiveComponent on playground. + +A custom component using ReactiveComponent diff --git a/content/docs/base-components/SelectedFilters.md b/content/docs/base-components/SelectedFilters.md index abd3ea7c5..52a7e6026 100644 --- a/content/docs/base-components/SelectedFilters.md +++ b/content/docs/base-components/SelectedFilters.md @@ -4,8 +4,8 @@ title: "SelectedFilters" layout: docs sectionid: docs permalink: base-components/selectedfilters.html -next: /list-components/singlelist.html -nextTitle: "List Components: SingleList" +next: reactivecomponent.html +nextTitle: "Reactive Component" redirect_from: - 'basic-components/selectedfilters.html' - 'base-components/selectedfilters' diff --git a/content/docs/base-components/nav.yml b/content/docs/base-components/nav.yml index 346c708c7..a2d7b586e 100644 --- a/content/docs/base-components/nav.yml +++ b/content/docs/base-components/nav.yml @@ -29,3 +29,20 @@ title: Examples href: /base-components/selectedfilters.html#examples forceInternal: true + - id: reactivecomponent + title: Reactive Component + href: /base-components/reactivecomponent.html + forceInternal: true + subitems: + - id: usage + title: Usage + href: /base-components/reactivecomponent.html#usage + forceInternal: true + - id: props + title: Props + href: /base-components/reactivecomponent.html#props + forceInternal: true + - id: demo + title: Demo + href: /base-components/reactivecomponent.html#demo + forceInternal: true From bb02062e1981b3155768bd78f87ee96d2dfe8a37 Mon Sep 17 00:00:00 2001 From: jyash97 Date: Thu, 25 Apr 2019 21:21:44 +0530 Subject: [PATCH 2/3] Update ReactiveComponent --- .../docs/base-components/ReactiveComponent.md | 116 ++++++++++++++---- 1 file changed, 93 insertions(+), 23 deletions(-) diff --git a/content/docs/base-components/ReactiveComponent.md b/content/docs/base-components/ReactiveComponent.md index 0144754c2..1cfbc9472 100644 --- a/content/docs/base-components/ReactiveComponent.md +++ b/content/docs/base-components/ReactiveComponent.md @@ -15,50 +15,110 @@ redirect_from: --- -With `ReactiveComponent`, you can convert any React Component into a Reactivesearch component i.e. your react component will be able to talk to other Reactivesearch components and connect with your elasticsearch cluster seamlessly. `Note` This page only cover `ReactiveComponent` with `customQuery`. Read more [here](/advanced/reactivecomponentindepth.html). +ReactiveComponent lets you connect any React UI component with an ElasticSearch query or an aggregation seamlessly. It can be used as a standalone component to integrate ElasticSearch queries into your frontend UI declaratively. It can also be used in conjunction with other ReactiveSearch components. Read more [here](/advanced/reactivecomponentindepth.html). > How does this work? > -> `ReactiveComponent` is a wrapper component that allows you to connect custom component(s) (passed as children) with the Reactivesearch ecosystem. +> `ReactiveComponent` supports a defaultQuery prop, which can take any ElasticSearch Query DSL object, and provides a callback onData prop which is called on successful query execution by ElasticSearch and can be used to create a side-effect in your app. There is also a render prop which can be used to render any React UI component of your choice which will have access to the hits and aggregations from the defaultQuery. ### Usage -Let's suppose - we are building an e-commerce store for cars which displays a list of cars of a particular brand on their separate page as `example.com/cars/nissan`. Now, we want all the filters on that page (like pricing, type of car, model, year, etc) to only show the data relevant to the given brand (i.e. `nissan`). In this case, `ReactiveComponent` can be used with `customQuery` to achieve the desired behavior easily. +Let's suppose - we are building an e-commerce store for cars which displays a list of cars and 5 popular car brands in tabs UI as the user selects a tab the result gets updated with the cars of selected brand. Now if the user wants to select other brand from tab, the results should be updated to new selected brand. In this case, `ReactiveComponent` can be used with `defaultQuery` to achieve the desired behavior easily. -We can then use the given ReactiveComponent to be watched by all the filters (via `react` prop) to avail the desired brand based filtering for all the filters. +We can then use the given ReactiveComponent to be watched by the result component (via `react` prop) to avail the desired brand based filtering for the results. -Check demo [here](https://codesandbox.io/s/3ylrrr0r5q). +Check demo [here](https://codesandbox.io/s/7zrj740oj6). ```js ({ - query: { - term: { - "brand.keyword": "Ford" - } - } + componentId="Brand" + showFilter + defaultQuery={() => ({ + aggs: { + 'brand.keyword': { + terms: { + field: 'brand.keyword', + order: { + _count: 'desc', + }, + size: 5, + }, + }, + }, + })} + render={data => { + return ; + }} +/> +``` + +You can also take advantage of various ReactiveSearch components static method for generating query. So we our basically selecting a single tab so we can use `SingleList` static method to generate query as follow: + +```js + ({ + ...SingleList.generateQueryOptions({ + dataField: "brand.keyword", + size: 5, + sortBy: "count" }) - } + })} + render={data => { + return ; + }} /> ``` +Here `TabComponent` is the component responsible to render the Tabs UI and handle switching tab and displaying selected filters. We are using `render` prop to display the component which provides a object with different params that can used in rendering UI and dispatching new query.Fow switching tab we will use `onClick` event on each tab to fire new query. We will make use of following param provided by `render` method: + +- **aggregations** `Object` + `aggregations` prop contains the results from `aggs` Elasticsearch query of the component. +- **setQuery** `function` + `setQuery` function sets the query of the component. It takes an object param of shape: +```javascript + { + query: {}, // query of the component + value: '' // value of the component + } +``` +- **value** `any` +`value` contains the current value of the component (which can be set via `setQuery()` function). This is used for URLParams and SelectedFilters. + +**SelectedFilters with ReactiveComponent** +For showing selected filters we will use [`SelectedFilters`](/base-components/selectedfilters.html). When we use `ReactiveComponent` we will need to maintain `SelectedFilters` value manually. To clear the selected value of `ReactiveComponent` use `onClear` prop on `SelectedFilter` and pass `null` in `setQuery`. + + +**ReactiveComponent and React context** +If the CustomComponent contains multiple react component which need to access ElasticSearch data we can take use of react [`context`](https://reactjs.org/docs/context.html) in order to pass data through the component tree without having to pass props down manually at every level. We can refactor the above example to use multiple child components and pass the data using context. You can check the refactored app demo [here](https://codesandbox.io/s/o9popzr47y). + + +**ReactiveComponent with Ant Design Component** +You can also easily connect component from design system to index data using `ReactiveComponent`. Check the example [here](https://codesandbox.io/s/mmkjv990nj) which connects `Dropdown` component of `Antd` with index data. + ### Props - -- **className** `String` + +- **className** `String` CSS class to be injected on the component container. -- **style** `Object` +- **style** `Object` CSS styles to be applied to the **DataSearch** component. -- **customQuery** `Function` +- **defaultQuery** `Function` + **returns** the default query to be applied to the component, as defined in Elasticsearch Query DSL. +- **customQuery** `Function` **returns** the custom query to be applied to the component, as defined in Elasticsearch Query DSL. Custom query can be used to change the component's behavior for its subscribers. -- **onQueryChange** `Function` +- **onQueryChange** `Function` is a callback function which accepts component's **prevQuery** and **nextQuery** as parameters. It is called everytime the component's query changes. This prop is handy in cases where you want to generate a side-effect whenever the component's query would change. -- **onAllData** `Function` - callback function which provides `hits` and `aggregations` as function params. +- **onData** `Function` + callback function which provides `data`, `rawData` and `aggregations` as function params. +- **showFilter** `Boolean` [optional] + show as filter when a value is selected in a global selected filters view. Defaults to `true`. +- **filterLabel** `String` [optional] + An optional label to display for the component in the global selected filters view. This is only applicable if `showFilter` is enabled. Default value used here is `componentId`. - **react** `Object` `react` prop is available in components whose data view should reactively update when on or more dependent components change their states, e.g. [`ReactiveMap`](/map-components/reactivemap.html), [`ReactiveList`](/basic-components/reactivelist.html). - **key** `String` @@ -71,13 +131,23 @@ Check demo [here](https://codesandbox.io/s/3ylrrr0r5q). - `Array` is used for specifying multiple components by their `componentId`. - `Object` is used for nesting other key clauses. -- **URLParams** `Boolean` [optional] +- **URLParams** `Boolean` [optional] enable creating a URL query string parameter based on the selected value of the list. This is useful for sharing URLs with the component state. Defaults to `false`. ### Demo - -See storybook for ReactiveComponent on playground. + +**ReactiveComponent with defaultQuery** +
+ + +**ReactiveComponent with defaultQuery and React context** +
+ + +**ReactiveComponent with defaultQuery and Antd component** +
+ A custom component using ReactiveComponent From a97d61ae08ad392df095f3737c83f6ada6b47f98 Mon Sep 17 00:00:00 2001 From: jyash97 Date: Mon, 6 May 2019 20:52:28 +0530 Subject: [PATCH 3/3] Update Content --- .../docs/base-components/ReactiveComponent.md | 46 ++++++++++--------- yarn.lock | 2 +- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/content/docs/base-components/ReactiveComponent.md b/content/docs/base-components/ReactiveComponent.md index 1cfbc9472..4b02c6b95 100644 --- a/content/docs/base-components/ReactiveComponent.md +++ b/content/docs/base-components/ReactiveComponent.md @@ -26,7 +26,7 @@ ReactiveComponent lets you connect any React UI component with an ElasticSearch Let's suppose - we are building an e-commerce store for cars which displays a list of cars and 5 popular car brands in tabs UI as the user selects a tab the result gets updated with the cars of selected brand. Now if the user wants to select other brand from tab, the results should be updated to new selected brand. In this case, `ReactiveComponent` can be used with `defaultQuery` to achieve the desired behavior easily. -We can then use the given ReactiveComponent to be watched by the result component (via `react` prop) to avail the desired brand based filtering for the results. +After selecting value from `ReactiveComponent` we will need to update result component with items satisfying the value, to achieve this we can take use of `react` prop. You can read more about the prop [here](/advanced/react.html). Check demo [here](https://codesandbox.io/s/7zrj740oj6). @@ -54,26 +54,7 @@ Check demo [here](https://codesandbox.io/s/7zrj740oj6). /> ``` -You can also take advantage of various ReactiveSearch components static method for generating query. So we our basically selecting a single tab so we can use `SingleList` static method to generate query as follow: - -```js - ({ - ...SingleList.generateQueryOptions({ - dataField: "brand.keyword", - size: 5, - sortBy: "count" - }) - })} - render={data => { - return ; - }} -/> -``` - -Here `TabComponent` is the component responsible to render the Tabs UI and handle switching tab and displaying selected filters. We are using `render` prop to display the component which provides a object with different params that can used in rendering UI and dispatching new query.Fow switching tab we will use `onClick` event on each tab to fire new query. We will make use of following param provided by `render` method: +Here `TabComponent` is responsible to render the Tabs UI and handle the switching between tabs and displaying selected filters. We are using `render` prop to display the component which provides an object with different parameters that can be used in rendering the UI and dispatching a new query. Fow switching the tab we will use `onClick` event to fire a new query. We will make use of the following paramateres provided by `render` method: - **aggregations** `Object` `aggregations` prop contains the results from `aggs` Elasticsearch query of the component. @@ -93,12 +74,33 @@ For showing selected filters we will use [`SelectedFilters`](/base-components/se **ReactiveComponent and React context** -If the CustomComponent contains multiple react component which need to access ElasticSearch data we can take use of react [`context`](https://reactjs.org/docs/context.html) in order to pass data through the component tree without having to pass props down manually at every level. We can refactor the above example to use multiple child components and pass the data using context. You can check the refactored app demo [here](https://codesandbox.io/s/o9popzr47y). +If the CustomComponent contains multiple react components which need to access ElasticSearch data we can take use of react [`context`](https://reactjs.org/docs/context.html) in order to pass data through the component tree without having to pass props down manually at every level. We can refactor the above example to use multiple child components and pass the data using context. You can check the refactored app demo [here](https://codesandbox.io/s/o9popzr47y). **ReactiveComponent with Ant Design Component** You can also easily connect component from design system to index data using `ReactiveComponent`. Check the example [here](https://codesandbox.io/s/mmkjv990nj) which connects `Dropdown` component of `Antd` with index data. +**ReactiveComponent Query using helper method** + +You can also take advantage of various ReactiveSearch components static method for generating query. So we our basically selecting a single tab so we can use `SingleList` static method to generate query as follow: + +```js + ({ + ...SingleList.generateQueryOptions({ + dataField: "brand.keyword", + size: 5, + sortBy: "count" + }) + })} + render={data => { + return ; + }} +/> +``` + ### Props diff --git a/yarn.lock b/yarn.lock index a5ebd9507..b515b1717 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5188,7 +5188,7 @@ graphql@0.10.5: graphql@^0.11.3, graphql@^0.11.7: version "0.11.7" - resolved "https://registry.npmjs.org/graphql/-/graphql-0.11.7.tgz#e5abaa9cb7b7cccb84e9f0836bf4370d268750c6" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.11.7.tgz#e5abaa9cb7b7cccb84e9f0836bf4370d268750c6" integrity sha512-x7uDjyz8Jx+QPbpCFCMQ8lltnQa4p4vSYHx6ADe8rVYRTdsyhCJbvSty5DAsLVmU6cGakl+r8HQYolKHxk/tiw== dependencies: iterall "1.1.3"