---
title: Expression
product: Form Library
description: Expression is a read-only question type that dynamically calculates values based on user input or predefined variables. This free demo for JavaScript shows how expressions can be used to estimate the total cost of a pizza order in real-time by multiplying the quantity by the price for each item on the menu and summing up these values.
framework: Vue 3
source: https://surveyjs.io/form-library/examples/expression-question-for-dynamic-form-calculations/vue3js
index: https://surveyjs.io/form-library/examples/overview.md
---

# Expression (Vue 3)

Expression is a read-only question type used to dynamically calculate values based on user input or predefined variables and display the calculated values in your form or survey. In this demo, expression questions calculate the cost of each pizza based on selected size and quantity and add up the costs to display the total of an order.

To create an Expression question, add an object to the [`elements`](https://surveyjs.io/form-library/documentation/api-reference/page-model#elements) array and specify the following properties within this object:

- `type`        
A question [type](https://surveyjs.io/form-library/documentation/api-reference/expression-model#getType). Set this property to `"expression"`.

- [`name`](https://surveyjs.io/form-library/documentation/api-reference/expression-model#name)        
A unique name that identifies the question.

- [`title`](https://surveyjs.io/form-library/documentation/api-reference/expression-model#title)       
A title for the question.

- [`expression`](https://surveyjs.io/form-library/documentation/api-reference/expression-model#expression)      
An expression used to calculate the value you want to display (see [Expressions](https://surveyjs.io/form-library/documentation/design-survey/conditional-logic#expressions)).

- *(Optional)* [`description`](https://surveyjs.io/form-library/documentation/api-reference/expression-model#description)       
Explanatory text displayed under the title.

Refer to the `json.js` file listing for more information.

## Files

### `public/index.html`

```html
<div id="app" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; height:100%"></div>
```

### `src/App.vue`

```html
<template>
    <SurveyComponent :model="survey" />
</template>
<script setup lang="ts">
    import { Model } from "survey-core";
    import { SurveyComponent } from "survey-vue3-ui";
    import "survey-core/survey-core.min.css";
    import "./index.css";
    import { json } from "./json";

    const survey = new Model(json);
    survey.onComplete.add((sender, options) => {
        console.log(JSON.stringify(sender.data, null, 3));
    });
</script>
```

### `src/index.css`

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

### `src/json.ts`

```ts
export const json = {
  "elements": [
    {
      "type": "panel",
      "name": "neapolitan",
      "elements": [
        {
          "type": "expression",
          "name": "price_n",
          "minWidth": "220px",
          "title": "Pizza Neapolitan",
          "description": "tomato sauce, mozzarella, anchovies, bazil",
          "expression": "5 + {size_n}",
          "displayStyle": "currency"
        },
        {
          "type": "image",
          "name": "pic_n",
          "width": "180px",
          "minWidth": "180px",
          "maxWidth": "180px",
          "startWithNewLine": false,
          "imageLink": "https://api.surveyjs.io/private/Surveys/files?name=c5b0302a-d6c8-46b4-ac57-7d519d0df0d1",
          "contentMode": "image",
          "imageFit": "cover",
          "imageHeight": 80,
          "imageWidth": 180
        },
        {
          "type": "dropdown",
          "name": "size_n",
          "minWidth": "220px",
          "title": "Size",
          "titleLocation": "left",
          "defaultValue": 1,
          "choices": [
            { "value": 0, "text": "Small" },
            { "value": 1, "text": "Medium" },
            { "value": 2, "text": "Large" }
          ],
          "allowClear": false
        },
        {
          "type": "dropdown",
          "name": "qty_n",
          "minWidth": "220px",
          "startWithNewLine": false,
          "title": "Qty",
          "titleLocation": "left",
          "choices": [ 1, 2, 3, 4, 5 ]
        }
      ]
    },
    {
      "type": "panel",
      "name": "pepperoni",
      "elements": [
        {
          "type": "expression",
          "name": "price_p",
          "title": "Pepperoni",
          "description": "tomato sauce, pepperoni, red peppers, onion",
          "expression": "5 + {size_p}",
          "displayStyle": "currency"
        },
        {
          "type": "image",
          "name": "pic_p",
          "width": "180px",
          "minWidth": "180px",
          "maxWidth": "180px",
          "startWithNewLine": false,
          "imageLink": "https://api.surveyjs.io/private/Surveys/files?name=8bcd88b7-df19-466d-8622-19100e400383",
          "contentMode": "image",
          "imageFit": "cover",
          "imageHeight": 80,
          "imageWidth": 180
        },
        {
          "type": "dropdown",
          "name": "size_p",
          "minWidth": "220px",
          "title": "Size",
          "titleLocation": "left",
          "defaultValue": 1,
          "choicesFromQuestion": "size_n",
          "allowClear": false
        },
        {
          "type": "dropdown",
          "name": "qty_p",
          "minWidth": "220px",
          "startWithNewLine": false,
          "title": "Qty",
          "titleLocation": "left",
          "choicesFromQuestion": "qty_n"
        }
      ]
    },
    {
      "type": "panel",
      "name": "marinara",
      "elements": [
        {
          "type": "expression",
          "name": "price_m",
          "title": "Marinara",
          "description": "tomato sauce, tuna, shrimps, mushrooms, cheese, onion",
          "expression": "5 + {size_m}",
          "displayStyle": "currency"
        },
        {
          "type": "image",
          "name": "pic_m",
          "width": "180px",
          "minWidth": "180px",
          "maxWidth": "180px",
          "startWithNewLine": false,
          "imageLink": "https://api.surveyjs.io/private/Surveys/files?name=24735b69-0ffe-4e49-9c90-1d9db1c8b83b",
          "contentMode": "image",
          "imageFit": "cover",
          "imageHeight": 80,
          "imageWidth": 180
        },
        {
          "type": "dropdown",
          "name": "size_m",
          "minWidth": "220px",
          "title": "Size",
          "titleLocation": "left",
          "defaultValue": 1,
          "choicesFromQuestion": "size_n",
          "allowClear": false
        },
        {
          "type": "dropdown",
          "name": "qty_m",
          "minWidth": "220px",
          "startWithNewLine": false,
          "title": "Qty",
          "titleLocation": "left",
          "choicesFromQuestion": "qty_n"
        }
      ]
    },
    {
      "type": "expression",
      "name": "total",
      "title": "Total",
      "expression": "{price_n} * {qty_n} + {price_m} * {qty_m} + {price_p} * {qty_p}",
      "displayStyle": "currency"
    }
  ],
  "questionErrorLocation": "bottom"
};
```

### `src/main.ts`

```ts
import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);
app.mount("#app");
```

### `src/shims-vue.d.ts`

```ts
/* eslint-disable */
declare module "*.vue" {
    import type { DefineComponent } from "vue"
    const component: DefineComponent<{}, {}, any>
    export default component
}
```

### `src/theme.ts`

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

### `.eslintrc.js`

```js
module.exports = {
    root: true,
    env: {
        node: true
    },
    extends: [
        "plugin:vue/vue3-essential",
        "eslint:recommended",
        "@vue/typescript/recommended",
        "@vue/prettier",
        "@vue/prettier/@typescript-eslint"
    ],
    parserOptions: {
        ecmaVersion: 2020
    },
    rules: {
        "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
        "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
    },
    overrides: [
        {
            files: [
                "**/__tests__/*.{j,t}s?(x)",
                "**/tests/unit/**/*.spec.{j,t}s?(x)"
            ],
            env: {
                jest: true
            }
        }
    ]
};
```

### `babel.config.js`

```js
module.exports = {
  presets: ["@vue/cli-plugin-babel/preset"]
};
```

### `package.json`

```json
{
  "name": "surveyjs-library-vue3",
  "version": "0.1.0",
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.5",
    "tslib": "2.6.1",
    "vue": "^3.4.1",
    "survey-core": "latest",
    "survey-vue3-ui": "latest",
    "vue-router": "^4.0.0-0",
    "vuex": "^4.0.0-0"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^2.33.0",
    "@typescript-eslint/parser": "^2.33.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-pwa": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^5.0.2",
    "@vue/test-utils": "^2.0.0-0",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-vue": "^7.0.0-0",
    "node-sass": "^4.12.0",
    "prettier": "^1.19.1",
    "sass-loader": "^8.0.2",
    "typescript": "~3.9.3"
  }
}
```

### `tsconfig.json`

```json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": [
      "webpack-env",
      "jest"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}
```

## Other Frameworks

- [Angular](https://surveyjs.io/form-library/examples/expression-question-for-dynamic-form-calculations/angular.md)
- [React](https://surveyjs.io/form-library/examples/expression-question-for-dynamic-form-calculations/reactjs.md)
- [jQuery](https://surveyjs.io/form-library/examples/expression-question-for-dynamic-form-calculations/jquery.md)
- [Vanilla JS](https://surveyjs.io/form-library/examples/expression-question-for-dynamic-form-calculations/vanillajs.md)
