---
title: Bind Sliders to Text Inputs
product: Form Library
description: Bind SurveyJS Single-Value Slider and Range Slider questions to text input fields in order to let users enter values manually in scenarios such as setting exact amounts or measurements. This demo explains how to set up two-way data binding between sliders and inputs so that changes in one are automatically reflected in the other.
framework: Angular
source: https://surveyjs.io/form-library/examples/sync-slider-with-input-fields/angular
index: https://surveyjs.io/form-library/examples/overview.md
---

# Bind Sliders to Text Inputs (Angular)

Sliders visually represent a value on a scale, but in some cases, it is easier to change the value by entering it in a text input field. For example, when a user needs to input a precise number&mdash;such as setting a temperature to 22.5&#8451; or specifying an exact budget amount&mdash;typing the value directly may be more efficient and accurate than adjusting a slider. This demo shows how you can bind a SurveyJS Slider and Range Slider to text input fields.

## Bind the Slider to a Text Input Field

To enable two-way binding between a Slider and a Single-Line Input question, follow the steps below:

1. Add a Slider and a Single-Line Input question to your survey.
2. Set the Slider's [`name`](/form-library/documentation/api-reference/questionslidermodel#name) property to a unique value.
3. Copy the Slider's `name` to the Single-Line Input question's [`valueName`](/form-library/documentation/api-reference/questionslidermodel#valueName) property.

This setup ensures that the Slider and the text input stay in sync&mdash;when the user changes one, the other updates automatically.

Additionally, you can configure the following optional features for better usability:

- Use the text input's [`min`](/form-library/documentation/api-reference/text-entry-question-model#min) and [`max`](/form-library/documentation/api-reference/text-entry-question-model#max) properties to restrict its values to the Slider's scale range.
- Set the text input's [`inputType`](/form-library/documentation/api-reference/text-entry-question-model#inputType) to `"number"` to enforce numeric input.
- Enable immediate updates by setting the text input's [`textUpdateMode`](/form-library/documentation/api-reference/survey-data-model#textUpdateMode) to `"onTyping"`.
- Place both questions in a [Panel](https://surveyjs.io/form-library/documentation/api-reference/panel-model) for better control over their layout and grouping.

## Bind the Range Slider to Text Input Fields

Binding a Range Slider is slightly different because it returns an array of two numbers (representing the selected range), whereas a text input can only store a single value.

To synchronize a Range Slider with two Single-Line Input questions, do the following:

1. Add a Range Slider and two Single-Line Input questions to your survey.
2. Set the [`name`](/form-library/documentation/api-reference/question#name) property for all those elements to unique values.
3. Set the Range Slider's [`setValueExpression`](/form-library/documentation/api-reference/questionslidermodel#setValueExpression) property to: `[{min-input-name}, {max-input-name}]`.
4. Specify each text input's [`setValueExpression`](/form-library/documentation/api-reference/text-entry-question-model#setValueExpression) property as follows:
   - For the minimum value input: `{range-slider-name[0]}`.
   - For the maximum value input: `{range-slider-name[1]}`.

This ensures the Range Slider and the input fields remain synchronized.

You can also apply the same optional settings described above&mdash;`min`, `max`, `inputType`, `textUpdateMode`, and layout grouping using a panel&mdash;for better user experience.

## Files

### `src/app/components/json.ts`

```ts
export const json = {
  "elements": [
    {
      "type": "panel",
      "name": "textual-entry-slider-panel",
      "title": "Slider + Text input field",
      "elements": [
        {
          "type": "slider",
          "name": "textual-entry-slider",
          "titleLocation": "hidden"
        },
        {
          "type": "text",
          "name": "textual-entry-textbox",
          "width": "120px",
          "minWidth": "100px",
          "startWithNewLine": false,
          "titleLocation": "hidden",
          "defaultValue": 0,
          "inputType": "number",
          "textUpdateMode": "onTyping",
          "min": 0,
          "max": 100,
          "valueName": "textual-entry-slider"
        }
      ]
    },
    {
      "type": "panel",
      "name": "textual-entry-range-panel",
      "title": "Range Slider + Text input fields",
      "elements": [
        {
          "type": "slider",
          "sliderType": "range",
          "name": "textual-entry-range",
          "titleLocation": "hidden",
          "setValueExpression": "[ {textual-entry-range-min}, {textual-entry-range-max} ]"
        },
        {
          "type": "text",
          "name": "textual-entry-range-min",
          "width": "50%",
          "minWidth": "200px",
          "title": "Min:",
          "titleLocation": "left",
          "setValueExpression": "{textual-entry-range[0]}",
          "defaultValue": "0",
          "inputType": "number",
          "textUpdateMode": "onTyping",
          "min": 0,
          "max": 100
        },
        {
          "type": "text",
          "name": "textual-entry-range-max",
          "width": "50%",
          "minWidth": "200px",
          "startWithNewLine": false,
          "title": "Max:",
          "titleLocation": "left",
          "setValueExpression": "{textual-entry-range[1]}",
          "defaultValue": "100",
          "inputType": "number",
          "textUpdateMode": "onTyping",
          "min": 0,
          "max": 100
        }
      ]
    }
  ],
  "widthMode": "static",
  "width": "670px"
};
```

### `src/app/components/survey.component.css`

```css
/* You can add your custom CSS here. */
```

### `src/app/components/survey.component.html`

```html
<survey [model]="model" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; height:100%"></survey>
```

### `src/app/components/survey.component.ts`

```ts
import { Component, OnInit } from "@angular/core";
import { Model } from "survey-core";
import { json } from "./json";
import "./survey.component.css";
import "survey-core/survey-core.min.css";

@Component({
    // tslint:disable-next-line:component-selector
    selector: "component-survey",
    templateUrl: "./survey.component.html",
    styleUrls: ["./survey.component.css"]
})
export class SurveyComponent implements OnInit {
    model: Model;
    ngOnInit() {
        const survey = new Model(json);
        survey.onComplete.add((sender, options) => {
            console.log(JSON.stringify(sender.data, null, 3));
        });
        this.model = survey;
    }
}
```

### `src/app/components/theme.ts`

```ts
export const themeJson = {};
```

### `src/app/app.component.css`

```css

```

### `src/app/app.component.html`

```html
<component-survey></component-survey>
```

### `src/app/app.component.ts`

```ts
import { Component } from "@angular/core";

@Component({
    selector: "app-root",
    templateUrl: "./app.component.html",
    styleUrls: ["./app.component.css"]
})
export class AppComponent {
    title = "CodeSandbox";
}
```

### `src/app/app.module.ts`

```ts
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";

import { AppComponent } from "./app.component";
import { SurveyModule } from "survey-angular-ui";
import { SurveyComponent } from "./components/survey.component";

@NgModule({
    declarations: [AppComponent, SurveyComponent],
    imports: [BrowserModule, SurveyModule],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }
```

### `src/environments/environment.prod.ts`

```ts
export const environment = {
    production: true
};
```

### `src/environments/environment.ts`

```ts
// The file contents for the current environment will overwrite these during build.
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `.angular-cli.json`.

export const environment = {
    production: false
};
```

### `src/index.html`

```html
<app-root></app-root>
```

### `src/main.ts`

```ts
import { enableProdMode } from "@angular/core";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";

import { AppModule } from "./app/app.module";
import { environment } from "./environments/environment";

if (environment.production) {
    enableProdMode();
}

platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .catch(err => console.log(err));
```

### `src/polyfills.ts`

```ts
/**
 * This file includes polyfills needed by Angular and is loaded before the app.
 * You can add your own extra polyfills to this file.
 *
 * This file is divided into 2 sections:
 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
 *      file.
 *
 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
 * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
 * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
 *
 * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
 */

/***************************************************************************************************
 * BROWSER POLYFILLS
 */

/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js';  // Run `npm install classlist.js`.

/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';

/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import "core-js/proposals/reflect-metadata";

/**
 * Required to support Web Animations `@angular/platform-browser/animations`.
 * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
 **/
// import 'web-animations-js';  // Run `npm install web-animations-js`.

/***************************************************************************************************
 * Zone JS is required by default for Angular itself.
 */
import "zone.js/dist/zone"; // Included with Angular CLI.

/***************************************************************************************************
 * APPLICATION IMPORTS
 */
```

### `src/styles.css`

```css
/* You can add your custom CSS here. */
```

### `src/typings.d.ts`

```ts
/* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
    id: string;
}
```

### `.angular-cli.json`

```json
{
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [ "assets", "favicon.ico" ],
      "index": "index.html",
      "main": "main.ts",
      "polyfills": "polyfills.ts",
      "prefix": "app",
      "styles": [ "styles.css" ],
      "scripts": [ ],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      }
    }
  ]
}
```

### `_tsconfig.json`

```json
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "allowSyntheticDefaultImports": true,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "resolveJsonModule": true,
    "target": "es2015",
    "module": "es2020",
    "lib": [
      "es2018",
      "dom"
    ]
  }
}
```

### `package.json`

```json
{
  "name": "surveyjs-angular",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "14.1.1",
    "@angular/cdk": "14.1.1",
    "@angular/common": "14.1.1",
    "@angular/compiler": "14.1.1",
    "@angular/core": "14.1.1",
    "@angular/forms": "14.1.1",
    "@angular/platform-browser": "14.1.1",
    "@angular/platform-browser-dynamic": "14.1.1",
    "@angular/router": "14.1.1",
    "core-js": "3.6.4",
    "rxjs": "6.5.4",
    "survey-core": "latest",
    "survey-angular-ui": "latest",
    "tslib": "1.13.0",
    "zone.js": "0.11.7"
  },
  "devDependencies": {
    "@angular/cli": "1.6.6",
    "@angular/compiler-cli": "^5.2.0",
    "@angular/language-service": "^5.2.0",
    "@types/core-js": "0.9.46",
    "@types/jasmine": "~2.8.3",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "~6.0.60",
    "codelyzer": "^4.0.1",
    "jasmine-core": "~2.8.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~2.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~4.1.0",
    "tslint": "~5.9.1",
    "typescript": "3.9.7"
  },
  "keywords": [ "angular", "surveyjs" ],
  "description": "SurveyJS-Angular example project"
}
```

## Other Frameworks

- [React](https://surveyjs.io/form-library/examples/sync-slider-with-input-fields/reactjs.md)
- [Vue 3](https://surveyjs.io/form-library/examples/sync-slider-with-input-fields/vue3js.md)
- [jQuery](https://surveyjs.io/form-library/examples/sync-slider-with-input-fields/jquery.md)
- [Vanilla JS](https://surveyjs.io/form-library/examples/sync-slider-with-input-fields/vanillajs.md)
