# Chapter 5

## Overview

In this chapter we will install a few extensions to enhance our application. The Servoy platform is highly extensible and it's easy add capabilities to your project.

## Key Concepts Covered

* **Servoy Extensions**
* **Servoy Package Manager** (SPM)
* **Modules**
* **Form Variables**
* **Search Module Extension**
* **Scopes**
* **Chart Component Extension**

## Add Search Capability

In this section, we will install a special extension to enable text-based searching of our database. Then we will bind it to a **TextBox** component and process user input to find records in our example database.

### Install a Search Module

Let's install the **SvySearch** module using the **Servoy Package Manger (SPM)**.

<figure><img src="/files/3WD7weCmV5MNGcGcfuAT" alt=""><figcaption><p>Install SvySearch module via the SPM</p></figcaption></figure>

1. At the top of your pallet, click "Get more components". This opens the SPM.
2. Click "Modules" and scroll down to locate "SvySearch" Click the `+` button to install it.

{% hint style="info" %}
**The Servoy Package Manager**

Also known as the **SPM**, it makes it easy to manage the **extensions** in your project.
{% endhint %}

The SvySearch module will be installed in your workspace and will be referenced as one of your solution's modules. You will find it located under the **Modules** mode in the **Solution Explorer**.

{% hint style="info" %}
**Modules**

Servoy is modular by design. Any Solution can be reused as a "Module" and it's easy to include modules in your application via the SPM. However, you can also create your own modules to simplify larger applications, reuse code and standardize development.
{% endhint %}

### Create a Form Variable

Because we will search based on user input, we will use a **Form Variable** to capture and reference the input.

<div align="left"><figure><img src="/files/EsedjXnp4bZXOXhkz1sx" alt="" width="375"><figcaption><p>Create Form Variable</p></figcaption></figure></div>

1. From the Solution Explorer, expand your `orders` form and locate the `variables` node.
2. Right-click and select "Create Variable" to open the **Form Variable Editor**.
3. Give your variable a name `searchText`, the Type as `TEXT` and the default `null` value.
4. This also opens the `orders.js`, showing your variable declaration in source.

{% code fullWidth="false" %}

```javascript
/**
 * @type {String}
 *
 * @properties={typeid:35,uuid:"02248C57-9D99-427A-99FB-748B405F2022"}
 */
var searchText = null;
```

{% endcode %}

{% hint style="info" %}
**Form Variables** work like any other Data Provider, such as database columns, except that they are not stored to a database. They hold session state, such as user input. You can also **manually type** the variable declaration into your form.js file.
{% endhint %}

### Add a Search Field

Let's add a field to the form and bind it to our form variable to capture the user input.

1. From the pallet, drag the **TextBox** component to the form, placing it above your orders grid.\
   (You can use the `cssPosition` property `10,75%,-1,10,140,30`)
2. Double-click the `dataProvider` property to open the **Data Provider Chooser**. Select the `searchText` form variable that you just created.
3. Edit the `placeholderText` property to be "Enter Search Criteria" This text will be displayed when the field is empty.

### Handle Input Event

To run the search, we'll need to bind an event handler to call the search module that we added. This time, we'll use the **onAction** event, which we've seen for buttons. However, for an input field, this will be triggered when the user hits the `ENTER` key.

1. Double-click the `onAction` event of the TextBox component that you just added. This opens the **Method Selection Wizard**.
2. Choose "Create method in Form". Name your method `onSearch` and select "Create Private". Click "OK and Show" to finish. The new method stub is opened in the `orders.js` file.
3. Let's add a few lines to the method. Don't be shy, you will get help from code completion based on the installed module.

{% code lineNumbers="true" %}

```javascript
function onSearch(event) {
	var search = scopes.svySearch.createSimpleSearch(foundset);
	search.setSearchAllColumns();
	search.setSearchText(searchText);
	search.loadRecords(foundset);
}
```

{% endcode %}

* Line `2` we access the **SvySearch** module and create a new search object based on this form's **DataSource** or **FoundSet**.
* Line`3` we indicate that the search will look across all `TEXT` columns in the data source.
* Line 4 we indicate that the search object should use the user input, captured in our form variable `searchText`.
* Line `5` we bring it home by applying the search object to this form's **FoundSet**. This will run the search and load records in our form.

{% hint style="info" %}
**Scopes**

You'll notice a new keyword `scopes` in this example. So far, we've only looked at form-level script files. Scopes are another kind of script file used to reference top-level packages of code in your solution and other modules. Enter `"scopes."` to get code completion on all available scopes.
{% endhint %}

Save your editors and preview the change in the NG Client. Enter some text in your search input field and hit `ENTER`.

<figure><img src="/files/fNUhZI2KaaJRhvR4To91" alt=""><figcaption><p>Search by Country</p></figcaption></figure>

Here you can see that the search module is able to match on all orders where the `shipcountry` column = Germany. Try it out! What happens when you enter a string fragment, such as "germ" or part of a city name instead?

### Search on Related Data

This is nice, but let's try something a little more...."advanced". Suppose we wanted to search on a customer name or a product in and order? Fortunately the **SvySearch** module is quite powerful and this can be done by adding just a little code.

<pre class="language-javascript" data-line-numbers><code class="lang-javascript">function onSearch(event) {
	var search = scopes.svySearch.createSimpleSearch(foundset);
	search.setSearchAllColumns();
	search.setSearchText(searchText);
	search.addSearchProvider('orders_to_customers.companyname');
<strong>	search.addSearchProvider('orders_to_order_details.order_details_to_products.productname');
</strong>	search.loadRecords(foundset);
}
</code></pre>

Let's examine the two lines of code added to enable a related search.

* Line `5` we add the related data provider for the company name
* Line `6` we add the order detail records and the related product name.

Save your editor and preview the results in the NG Client.

Enter "big" and you will match on the orders of the customer "The Big Cheese". Enter "coffee Germany" and you will match on all orders shipped to Germany having coffee as one of the products.

{% hint style="success" %}
**Robust Searching**\
Well done. You added a robust user text search to your application in just a few lines of code. The Servoy platform handles all the parsing of terms, caching and querying. This approach works equally well on very large databases.
{% endhint %}

## Add a Chart Component

Let's finish the chapter by adding a simple chart to our orders form to help visualize the breakdown of the products. It takes just a few clicks and demonstrates how to add extend your pallet of components.

### Install the ChartJS Component

In the previous example, we added a **module**, which included some code libraries we took advantage of. In this example, we'll add a new **component** package.

<figure><img src="/files/W4B4yJam5wyaaNzDSmI4" alt=""><figcaption><p>Chart Component</p></figcaption></figure>

1. Open the **Servoy Package Manager** (SPM) as you did in the previous example. In the list of components, scroll to find the **ChartJS** package and click the `+` button to install.
2. After the package installs, the component is available drag a chart component from the pallet onto your form.
3. You may position the component right of your input fields, by setting the `cssProperty` to `86,-1,-1,calc(25% + 390px),200,170`
4. Next, we'll set the data binding for the component. Double-click the `foundset` property to open the **Foundset Chooser**. Select your `orders_to_order_details` relation and click `OK`.
5. Expand the `dataproviders` sub-property and double-click the `label` property to open the Data Provider Chooser. Select `order_details_to_products.productname.` This will be the display value for the chart.
6. Do the same for the `value` sub-property and choose the `subtotal` calculation that you made in a previous chapter.
7. Just for fun, let's switch the chart type. Edit the `type` property and select `DOUGHNUT`.

Save your editors and preview the changes in the NG Client.

<div align="left"><figure><img src="/files/tuTJdaSGja0yykgxmqMd" alt=""><figcaption><p>Chart Component Preview</p></figcaption></figure></div>

You can see that the chart labels match the product name and the values match the subtotal. When the selected order record changes, the chart is redrawn. Moreover, when the input values to the subtotal calculation change (i.e. unit price), the chart is redrawn.

{% hint style="success" %}
**Data-Bound Components**\
Nice work! In only a few clicks (and zero lines of code) you have a working chart. Most UI Components in Servoy are data-bound by default, meaning they *always* reflect the real-time values in the connected data source....automatically.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.servoy.com/guides/get-started/chapter-5.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
