How to Create a Settings Page

Contents

Overview

This article introduces how to create a Kintone plug-in's settings page.

The App used in this article is based on the following article:
How to Create Kintone Plug-ins

Creating a plug-in settings page allows end users to set values that will be used in the JavaScript customization.

STEP 1: Complete the Steps in the Previous Article

Complete the steps in the following article:
How to Create Kintone Plug-ins

STEP 2: Create an HTML file for the Plug-in Settings Page

Create an "html" directory under the "sample-plugin" directory.

1
2
3
4
5
sample-plugin
 ├── html <=== directory to be created
 ├── image
 ├── js
 └── manifest.json

Next, create an HTML file and name it "config.html". Save it under the "html" directory. This HTML file will be used for creating the plug-in settings page.

Set up the HTML, so that users can input field codes into text boxes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div>
  <div class="setting">
    <label class="kintoneplugin-label" for="checkvalue-field-tel">
      <span>Check the Telephone value</span>
      <span class="kintoneplugin-require">*</span>
    </label>
    <div class="kintoneplugin-row">Input the field code</div>
    <div class="kintoneplugin-input-outer">
      <input id="checkvalue-field-tel" class="kintoneplugin-input-text" type="text">
    </div>
  </div>
  <div class="setting">
    <label class="kintoneplugin-label" for="checkvalue-field-mail">
      <span>Check the Email value</span>
      <span class="kintoneplugin-require">*</span>
    </label>
    <div class="kintoneplugin-row">Input the field code</div>
    <div class="kintoneplugin-input-outer">
      <input id="checkvalue-field-mail" class="kintoneplugin-input-text" type="text">
    </div>
  </div>
  <div class="setting">
    <button type="button" id="submit" class="kintoneplugin-button-dialog-ok">save</button>
    <button type="button" id="cancel" class="kintoneplugin-button-dialog-cancel">cancel</button>
  </div>
</div>

In this sample code, the class name is set so that the 51-modern-default style is applied. 51-modern-default styles HTML elements on the plug-in settings page to fit in with Kintone's UI. Refer to the following link for more details:
51-modern-default (External link)

The details of the class and id names are as follows.

  • Class names starting with kintoneplugin- are CSS class names to which 51-modern-default is applied.
  • The setting class is used for the CSS settings .
  • The id names starting with checkvalue-field- are used in the JavaScript settings .

STEP 3: Create a CSS file for the Plug-in Settings Page

Create a "css" directory under the "sample-plugin" directory.

1
2
3
4
5
6
sample-plugin
 ├── css <=== directory to be created
 ├── html
 ├── image
 ├── js
 └── manifest.json

Next, prepare two CSS files to style the settings page:

  • 51-modern-default.css
    Save the contents of the 51-modern-default.css file and name it "51-modern-default.css".
    51-modern-default.css (External link)

  • config.css
    Save the following contents into a file named "config.css". This code adjusts the margins of the div elements.

    1
    2
    3
    
    .setting {
      padding: 0 0 20px 0;
    }

Save both files under the "css" directory.

STEP 4: Create a JavaScript file for the Plug-in Settings Page

The JavaScript file preforms the following operations on the settings page:

  • If available, get the plug-in settings that were previously set by the user, and display the values as initial values on the form.
  • Click the Cancel button to navigate back to the App's Plug-ins page without saving the settings.
  • Click the Save button to check the required and duplicated fields. In case of errors, show error messages. If successful, save the settings, and navigate the user back to the App's Plug-ins page.

Save the following contents into a file named "config.js". Save it under the "js" directory.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
(async (PLUGIN_ID) => {
  'use strict';

  // escape values
  const escapeHtml = (htmlstr) => {
    return htmlstr
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;')
      .replace(/\n/g, '&#xA;');
  };

  // get form information
  const telFormData = document.getElementById('checkvalue-field-tel');
  const mailFormData = document.getElementById('checkvalue-field-mail');

  // get configuration settings
  const config = kintone.plugin.app.getConfig(PLUGIN_ID);

  // set initial value
  telFormData.value = config.tel || '';
  mailFormData.value = config.mail || '';

  // get app id
  const appId = kintone.app.getId();

  // save button
  const saveButton = document.getElementById('submit');
  saveButton.addEventListener('click', () => {
    const tel = escapeHtml(telFormData.value);
    const mail = escapeHtml(mailFormData.value);
    // required values check
    if (tel === '' || mail === '') {
      alert('Required value is missing.');
      return;
    }
    // duplicated values check
    if (new Set([tel, mail]).size < 2) {
      alert('Duplicate values.');
      return;
    }
    // save plugin configuration settings
    const newConfig = {tel, mail};
    kintone.plugin.app.setConfig(newConfig, () => {
      // redirect to the app settings page
      window.location.href = `/k/admin/app/flow?app=${appId}`;
    });
  });

  // cancel button
  const cancelButton = document.getElementById('cancel');
  cancelButton.addEventListener('click', () => {
    // redirect to the list of plug-ins screen after clicking the cancel button
    window.location.href = `/k/admin/app/${appId}/plugin/`;
  });
})(kintone.$PLUGIN_ID);

Code Explanation

Get the plug-in configuration settings

The configuration settings of the plug-in is retrieved using the Get Config API. The argument pluginId is the plugin ID.

In this immediately invoked function, the plug-in ID is provided with kintone.$PLUGIN_ID. This is passed on to the PLUGIN_ID parameter of the function. The parameter is used by the getConfig() function to get the plug-in configuration settings.

1
2
3
4
((PLUGIN_ID) => {
  'use strict';
  const config = kintone.plugin.app.getConfig(PLUGIN_ID);
})(kintone.$PLUGIN_ID);
Display the retrieved configuration settings

If available, the plug-in settings are retrieved and the values are displayed as initial values on the form.

The form information is retrieved using an id name starting with checkvalue-field-.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
((PLUGIN_ID) => {
  'use strict';
  // get configuration settings
  const config = kintone.plugin.app.getConfig(PLUGIN_ID);
  // get form information
  const telFormData = document.getElementById('checkvalue-field-tel');
  const mailFormData = document.getElementById('checkvalue-field-mail');
  // set as initial value
  telFormData.value = config.tel || '';
  mailFormData.value = config.mail || '';
})(kintone.$PLUGIN_ID);
Set the cancel button

The cancel button is implemented. The path is set to /k/admin/app/{APP_ID}/plugin/, which is the Plug-in list page of the App. The {APP_ID} is the App ID of the Kintone App and is obtained by using the Get App ID API:
Get App ID

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  // get app id
  const appId = kintone.app.getId();

  // cancel button
  const cancelButton = document.getElementById('cancel');
  cancelButton.addEventListener('click', () => {
  // redirect to the list of plug-ins screen after clicking the cancel button
    window.location.href = `/k/admin/app/${appId}/plugin/`;
  });
})(kintone.$PLUGIN_ID);
Set the save button

When the Save button is clicked, the following checks are performed on the values in the form:

  • Checks for required values
    If any required values are missing, error messages will be displayed.
  • Checks for duplicated values
    If duplicated values are entered in the form, error messages will be displayed.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// save button
const saveButton = document.getElementById('submit');
saveButton.addEventListener('click', () => {
  const tel = escapeHtml(telFormData.value);
  const mail = escapeHtml(mailFormData.value);
  // required values check
  if (tel === '' || mail === '') {
    alert('Required value is missing.');
    return;
  }
  // duplicated values check
  if (new Set([tel, mail]).size < 2) {
    alert('Duplicate values.');
    return;
  }
});

To prevent Cross-Site Scripting (XSS), the escapeHtml() function is used to escape the selected values.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// escape values
const escapeHtml = (htmlstr) => {
  return htmlstr
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;')
    .replace(/\n/g, '&#xA;');
};
Save the plug-in settings

If all checks are passed, the plug-in configuration settings will be saved in the plug-in using the Set Config API.
Set Config

The config parameter for the API is the plug-in configuration settings to be saved. In this case, an object named newConfig.

The second argument, successCallback, can be used for the process that follows after the configuration is saved, which is navigating back to the App Settings page. The path to the App Settings page is /k/admin/app/flow?app={APP_ID}.

1
2
3
4
5
6
// save plugin configuration settings
const newConfig = { tel, mail};
kintone.plugin.app.setConfig(newConfig, () => {
  // redirect to the app settings page
  window.location.href = `/k/admin/app/flow?app=${appId}`;
});

STEP 5: Update the Desktop JavaScript File

Update the Desktop JavaScript file so that it can use values saved in the plug-in configuration settings. This allows developers to avoid hard-coding field code names into the code.

Edit the "desktop.js" file created in the following article:
How to Create Kintone Plug-ins

Use the Get Config API to get the plug-in's configuration settings.
Get Config

Assign the retrieved plug-in configuration settings to the config variable. Set field codes that will be used in this code, from this object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
((PLUGIN_ID) => {
  'use strict';

  // get plugin configuration settings
  const config = kintone.plugin.app.getConfig(PLUGIN_ID) || {};

  // if there is no settings, exit the function
  if (Object.keys(config).length === 0) {
    return;
  }

  // telephone field code
  const telFieldCode = config.tel;
  // email field code
  const mailFieldCode = config.mail;

  // check the Telephone value
  const validateTel = (event) => {
    // set the telephone pattern, number must be 10 or 11 digits
    const telPattern = /^\d{10,11}$/;
    const record = event.record;
    record[telFieldCode].error = null;

    // check the input value
    const telFieldValue = record[telFieldCode].value;
    if (telFieldValue) {
      if (!(telFieldValue.match(telPattern))) {
        // error if the input value does not match the pattern
        record[telFieldCode].error = 'Telephone number must be 10 or 11 digits.';
      }
    }
  };

  // check the Email value
  const validateMail = (event) => {
    // set the email pattern
    const mailPattern = /^([a-zA-Z0-9])+([a-zA-Z0-9._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9._-]+)+$/;
    const record = event.record;
    record[mailFieldCode].error = null;
    // check the input value
    const mailFieldValue = record[mailFieldCode].value;
    if (mailFieldValue) {
      if (!(mailFieldValue.match(mailPattern))) {
        // error if the input value does not match the pattern
        record[mailFieldCode].error = 'Invalid email address.';
      }
    }
  };

  // Telephone field change event
  kintone.events.on([
    'app.record.create.change.' + telFieldCode,
    'app.record.edit.change.' + telFieldCode,
    'app.record.index.edit.change.' + telFieldCode
  ], (event) => {
    validateTel(event);
    return event;
  });

  // Email field change event
  kintone.events.on([
    'app.record.create.change.' + mailFieldCode,
    'app.record.edit.change.' + mailFieldCode,
    'app.record.index.edit.change.' + mailFieldCode
  ], (event) => {
    validateMail(event);
    return event;
  });

  // record save events
  kintone.events.on([
    'app.record.create.submit',
    'app.record.edit.submit',
    'app.record.index.edit.submit'
  ], (event) => {
    validateTel(event);
    validateMail(event);
    return event;
  });
})(kintone.$PLUGIN_ID);

STEP 6: Update the Manifest.json File

Update the Manifest.json file to add the path to the new files created in this tutorial.

The key config.required_params specifies an array of key names for the required fields. These keys are the keys within the object that are set with the Set Config API.

This allows the message "Required field has not been set" to be displayed on the App's Plug-in list page, if the required fields are not saved with setConfig().

Update version to indicate that the plug-in has been updated.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
    "manifest_version": 1,
    "version": "1.1.0",
    "type": "APP",
    "name": {
      "en": "Input value check plug-in"
    },
    "description": {
      "en": "This plugin checks telephone number and e-mail address"
    },
    "icon": "image/check.png",
    "homepage_url": {
      "en": "https://kintone.dev/en/plugins/development-guide/how-to-create-plugins/"
    },
    "desktop": {
      "js": [
        "js/desktop.js"
      ]
    },
    "config": {
    "html": "html/config.html",
    "js": [
      "js/config.js"
    ],
    "css": [
      "css/51-modern-default.css",
      "css/config.css"
    ],
    "required_params": ["tel", "mail"]
    }
  }

Directory structure

Once all the files are prepared, the file tree should now look like the following structure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
sample-plugin
├── css
│   ├── 51-modern-default.css
│   └── config.css
├── html
│   └── config.html
├── image
│   └── check.png
├── js
│   ├── config.js
│   └── desktop.js
└── manifest.json

STEP 7: Repackage and Upload the Plug-in

Follow the steps in the following article to repackage the plug-in:
Package the Plug-in Files

To repackage, specify the private key file in the --ppk option.

1
kintone-plugin-packer sample-plugin --ppk {private_key_file}.ppk

Follow the steps in the following article to install the plug-in into Kintone:
Install the Plug-in into Kintone

If the file was uploaded successfully, the version added in "manifest.json" will be displayed under the plug-in name on the Plug-ins page.

STEP 8: Test the Plug-in

From the App Settings page, click on Plug-ins. Click on the gear button to set the field codes.

Enter the field codes into the text fields.

For the Customer Database App, the field codes are as follows:

Field Name Field Code
Telephone # telephone_number
Email email

Confirm that the following operations work:

  • Clicking the cancel button will redirect the user to the Plug-ins Settings page
  • Clicking the save button without entering a value will cause an error message to appear.

  • Setting duplicate values and clicking save will cause an error message to appear.

  • After entering all the values and clicking save, users will be redirected to the App Settings page.
  • On the Plug-in Settings page, the values that were previously set are displayed as the initial values.

Navigate to the App and add a new record. Enter invalid values for the Email and Telephone Number; an error message should be displayed.