Пошаговое руководство по созданию опроса удовлетворенности сотрудников с использованием Angular и SurveyJS, бесплатной библиотеки опросов с открытым исходным кодом.

Первоначально написано SIHEM BOUHENNICHE.

Оглавление

  • Введение
  • Почему SurveyJS?
  • Создание опроса
  • Настройте проект Angular
  • Установите и настройте SurveyJS
  • Создайте опрос удовлетворенности сотрудников
  • Настроить базу данных MongoDB
  • Сохранять результаты в коллекции MongoDB
  • Заключение

Введение

Опросы удовлетворенности сотрудников могут обеспечить ряд преимуществ как для сотрудников, так и для работодателей.

Для сотрудников опросы удовлетворенности могут помочь им почувствовать, что их работодатель их слышит и ценит, что может повысить моральный дух и удовлетворенность работой.

Для работодателей опросы удовлетворенности могут дать ценную информацию о том, что работает хорошо, а какие области нуждаются в улучшении в организации. Это может помочь работодателям принимать обоснованные решения о том, как поддержать своих сотрудников и улучшить общую рабочую среду.

Удовлетворенные сотрудники более продуктивны и вовлечены в свою работу, что может привести к увеличению ценности бизнеса. И наоборот, если в вашей организации есть недовольные люди, вы снизите прибыльность. Всегда полезно держать руку на пульсе, и подобные внутренние опросы могут помочь.

В этой статье мы построим такой опрос, но прежде чем двигаться дальше, давайте взглянем на технологии, которые мы будем использовать:

  • Angular: среда проектирования приложений и платформа разработки для создания одностраничных приложений.
  • SurveyJS: бесплатный конструктор форм на JavaScript с открытым исходным кодом (ссылка на Github), который значительно упрощает и упрощает создание самостоятельных форм.
  • MongoDB: база данных, ориентированная на документы. Классифицируется как база данных без SQL. MongoDB использует документы в формате JSON с дополнительными схемами.

Кто-то может возразить, что Angular, несмотря на то, что он является предпочтительным корпоративным фреймворком, не дает разработчикам большого опыта для создания опросов, которые хорошо масштабируются с большим количеством вопросов. Но в этой статье вы найдете элегантный способ разработки корпоративного опроса с использованием Angular — без пары ngIf и ng-template для каждого вопроса, который вы хотите отображать условно, или набора привязок.

Здесь на помощь приходит SurveyJS. Используя эту библиотеку с открытым исходным кодом, мы можем упростить создание форм и управление ими в динамическом режиме. Мы рассмотрим это более подробно далее. А пока давайте посмотрим, какие вопросы мы собираемся задать в нашем опросе.

Вопросы этого опроса подробно описаны в таблице ниже:

Наш опрос удовлетворенности сотрудников будет охватывать множество вопросов, чтобы определить, удовлетворены ли сотрудники своей ролью, и если нет, то почему.

В следующем разделе мы увидим, почему мы собираемся использовать SurveyJS в качестве предпочтительного инструмента для создания этого опроса.

Почему SurveyJS?

Следующие причины показывают, почему мы должны использовать SurveyJS в сочетании с Angular для нашей задачи вместо того, чтобы разрабатывать наши формы/опросы вручную с помощью примитивов Angular.

  • Создавайте самостоятельные опросы. Таким образом, мы можем защитить наши данные и хранить их в выбранной нами базе данных, а не использовать другие онлайн-сервисы, такие как Google Forms, которые сохраняют наши результаты в файлах Google Sheets.
  • Легко создавайте сложные опросы, включающие условную логику и ветвление, а также делайте наши формы более явными и адаптируемыми ко многим случаям без необходимости встраивать дополнительный JavaScript.
  • Создавайте динамические формы, которые можно легко обновлять. Формы SurveyJS основаны на модели data-first, поэтому нам нужно просто обновить модель формы JSON.
  • Включите различные компоненты ввода с проверкой, такие как многострочный ввод, флажки, раскрывающиеся списки, матричные анкеты, загрузка файлов и многое другое, что дает нам больше гибкости при разработке форм и опросов.
  • Создавайте многоязычные опросы. Таким образом, мы можем просто создать один опрос, а не создавать множество опросов для каждого языка.

В дополнение ко всем этим преимуществам SurveyJS дает нам возможность использовать либо их красивые компоненты формы, либо мы можем настроить все с помощью CSS и сделать эти компоненты более персонализированными и соответствующими нашей фирменной теме.

Теперь пришло время начать строительство. Давайте углубимся в это.

Создание опроса

Шаг 1: Настройте проект Angular

Во-первых, мы должны убедиться, что у нас установлена последняя версия Angular CLI.

npm install -g @angular/cli

Мы можем узнать больше об Angular CLI и найти более подробную информацию об установке здесь.

После установки Angular CLI мы можем создать наше приложение Angular с помощью команды ng, как показано ниже:

ng new employee-satisfaction-survey-app

Эта команда сгенерирует наше приложение со следующей структурой:

Шаг 2: Установите и настройте SurveyJS

Теперь, когда мы создали наше приложение, давайте установим библиотеку SurveyJS (более подробную информацию об установке вы можете найти в официальной документации) с помощью кода ниже:

npm install survey-angular-ui — save

Как только SurveyJS будет установлен, мы начнем настройку:

Шаг 2.1. Ссылка на пользовательский интерфейс таблиц стилей SurveyJS в angular.json

SurveyJS поставляется с двумя разными таблицами стилей Modern и DefaultV2, показанными на рисунке ниже:

{
  “$schema”: “./node_modules/@angular/cli/lib/config/schema.json”,
  “version”: 1,
  “newProjectRoot”: “projects”,
  “projects”: {
    “employee-satisfaction-survey-app”: {
      “projectType”: “application”,
      “schematics”: {},
      “root”: “”,
      “sourceRoot”: “src”,
      “prefix”: “app”,
      “architect”: {
        “build”: {
          “builder”: “@angular-devkit/build-angular:browser”,
          “options”: {
            …
            “styles”: [
              “src/styles.css”,
              “node_modules/survey-core/defaultV2.min.css”,
              // Modern theme
              “node_modules/survey-core/modern.min.css”
            ],
            “scripts”: []
          },
          “configurations”: {
            …
          },
          “defaultConfiguration”: “production”
        },
        “serve”: {
          …
        },
        “extract-i18n”: {
          …
        },
        “test”: {
          …
        }
      }
    }
  }
}

Шаг 2.2. Примените указанную тему в компоненте приложения

Для этого мы будем использовать метод StyleManager.applyTheme(theme-name); и передадим имя темы в качестве параметра (“modern” или “defaultV2”).

import { StylesManager } from “survey-core”;

StylesManager.applyTheme(“modern”);

Шаг 2.3. Создайте модель опроса

Согласно документации SurveyJS:

Модель описывает макет и содержание вашего опроса. Простейшая модель опроса содержит один или несколько вопросов без изменения макета.

Модель состоит из объекта JSON, который объявляет наши вопросы и их типы. Этот объект JSON называется схемой.

Например, эта простая схема содержит один вопрос, объявленный в массиве elements.

const surveyJson = {
  elements: [ // every element contains a question
   {
     name: ‘Name’,// field name
     title: ‘Enter your full name:’,// field title
     type: ‘text’,// field type
   },
  ],
};

Затем давайте создадим экземпляр модели, передав схему конструктору Model, как показано в коде ниже:

import { Component, OnInit } from ‘@angular/core’;
import { Model, StylesManager } from “survey-core”;

StylesManager.applyTheme(‘modern’);

const surveyJson = {
  elements: [
  {
     name: ‘Name’,
     title: ‘Enter your full name:’,
     type: ‘text’,
  },
 ],
};

@Component({
   selector: ‘app-root’,
   templateUrl: ‘./app.component.html’,
   styleUrls: [‘./app.component.css’],
})
export class AppComponent implements OnInit {
  title = ‘employee-satisfaction-survey-app’;
  surveyModel: Model | undefined;

  ngOnInit() {
    const survey = new Model(surveyJson);
    this.surveyModel = survey;
  }
}

Шаг 2.4. Добавьте модуль SurveyJS в app.module.ts

Чтобы отобразить наш опрос, нам нужно импортировать модуль библиотеки форм SurveyJS в app.module.ts.

import { NgModule } from ‘@angular/core’;
import { BrowserModule } from ‘@angular/platform-browser’;
import { AppRoutingModule } from ‘./app-routing.module’;
import { AppComponent } from ‘./app.component’;
import { SurveyModule } from ‘survey-angular-ui’;

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

Затем мы просто добавим элемент <survey> в наш шаблон компонента и передаем экземпляр модели, который мы создали выше, как атрибут model:

<survey [model]=”surveyModel”></survey>

Шаг 2.5. Запустите приложение

Наконец, давайте запустим наше приложение:

npm run start

Если вы выполнили эти шаги, вы получите следующий результат:

Шаг 3: Создайте опрос удовлетворенности сотрудников

Теперь давайте сосредоточимся на схеме опроса и посмотрим, как использовать различные типы компонентов в соответствии с каждым вопросом нашего опроса удовлетворенности.

Если мы посмотрим на наш опрос удовлетворенности, мы увидим, что нам нужны 4 типа компонентов:

  • Простое текстовое поле: text
  • Поле простой текстовой области: comment
  • Поле группы радио: radiogroup
  • Матрица радиогрупп: matrix

Для получения более подробной информации о различных компонентах, предоставляемых SurveyJS, вы можете взглянуть на API библиотеки форм.

После исправления необходимых компонентов давайте обновим нашу схему JSON:

const surveyJson = {
  title: ‘Your opinion counts!’,
  description: ‘Please express what you think about your job?’,
  pages: [
   {
     elements: [
       {
         name: ‘Name’,
         title: ‘Enter your full name:’,
         type: ‘text’,
       },
       {
         name: ‘OverallSatisfaction’,
         title:
           ‘How would you describe your overall level of job satisfaction?’,
         type: ‘radiogroup’,
         isRequired: true,
         choices: [
           ‘Very satisfied’,
           ‘Satisfied’,
           ‘Neutral’,
           ‘Dissatisfied’,
           ‘Very dissatisfied’,
         ],
       },
       {
         name: ‘Quality’,
         title: ‘How would you rate the following?’,
         type: ‘matrix’,
         isRequired: true,
         columns: [
           {
             value: 1,
             text: ‘Very poor’,
           },
           {
             value: 2,
             text: ‘Poor’,
           },
           {
             value: 3,
             text: ‘Average’,
           },
           {
             value: 4,
             text: ‘Good’,
           },
           {
             value: 5,
             text: ‘Excellent’,
           },
         ],
         rows: [
           {
             value: ‘Salary’,
             text: ‘Salary’,
           },
           {
             value: ‘OverallBenefits’,
             text: ‘Overall benefits’,
           },
           {
             value: ‘HealthBenefits’,
             text: ‘Health benefits’,
           },
           {
             value: ‘PhysicalWorkEnvironment’,
             text: ‘Physical work environment’,
           },
           {
             value: ‘TrainingOpportunities’,
             text: ‘Training opportunities’,
           },
           {
             value: ‘WorkingTimeFlexibility’,
             text: ‘Working time flexibility’,
           },
         ],
       },
       {
         name: ‘ValuedAtWork’,
         title: ‘Do you feel valued at work?’,
         type: ‘radiogroup’,
         isRequired: true,
         choices: [‘Yes’, ‘No’],
       },
       {
         name: ‘Explanation’,
         title: ‘If no please explain’,
        
         visibleIf: “{ValuedAtWork}=’No’”,
         type: ‘comment’,
       },
       {
         name: ‘Feedback’,
         title: ‘Please Provide Any Additional Feedback’,
         type: ‘comment’,
       },
     ],
   },
 ],
};

Примечание.

  • Чтобы пометить вопрос как обязательный, просто добавьте свойство isRequired.
  • Для установки типа вопроса мы используем свойство type.
  • Чтобы показать некоторые поля, когда условие выполнено, мы используем свойство visibleIf.

Затем сохраните и обновите наше приложение, чтобы увидеть изменения в браузере:

Чтобы обработать завершение опроса после его завершения пользователем, мы должны использовать обработчик события onComplete. Например, давайте просто зарегистрируем (распечатаем) результаты в консоли браузера.

Добавьте следующий код в свой app.component.ts:

import { Component, OnInit } from ‘@angular/core’;
import { Model, StylesManager } from ‘survey-core’;

// const SURVEY_ID = 1;

StylesManager.applyTheme(‘modern’);

const surveyJson = {
  …
};

@Component({
  selector: ‘app-root’,
  templateUrl: ‘./app.component.html’,
  styleUrls: [‘./app.component.css’],
})
export class AppComponent implements OnInit {
  title = ‘My First Survey’;
  surveyModel: Model;
  logSurveyResults(sender) {
    console.log(sender.data);
  }
  ngOnInit() {
    const survey = new Model(surveyJson);
    survey.onComplete.add(this.logSurveyResults);
    this.surveyModel = survey;
  }
}

Сохраните, обновите и откройте консоль браузера, чтобы увидеть результаты, отображаемые там после прохождения опроса:

Теперь, когда мы создали наш опрос, мы увидим, как настроить базу данных для хранения данных опроса.

Шаг 4: Настройте базу данных MongoDB

В реальных приложениях мы не регистрируем результаты в консоли, но будем использовать эти результаты в других веб-сервисах. Фактически мы должны отправлять результаты на сервер, где они будут храниться в базе данных и обрабатываться системой.

Чтобы сделать наш пример более полным, мы создадим простой API, используя Express и MongoDB. Этот API будет получать результаты нашего опроса удовлетворенности и сохранять их в базе данных.

Начнем с того, что у нас установлены node, npm и MongoDB (вы можете скачать их здесь).

$ node -v
$ npm -v
$ mongo -v

Затем мы создаем наше приложение Node.js и устанавливаем необходимые пакеты. Для этого мы будем использовать:

  • Express: минимальная платформа веб-приложений Node.js, предоставляющая набор функций для веб-приложений и мобильных приложений.
  • Nodemon: инструмент, который помогает разрабатывать приложения на основе Node.js, автоматически перезапуская приложение узла при обнаружении изменений файлов в каталоге.
  • Mongoose: объектное моделирование MongoDB для Node.js.
$ mkdir employee-satisfaction-survey-api
$ cd employee-satisfaction-survey-api
$ npm init
$ npm install express nodemon mongoose — save

После этого мы создадим следующую структуру приложения:

  • package.json:
{
  “name”: “employee-satisfaction-survey-api”,
  “version”: “1.0.0”,
  “description”: “Employee satisfaction survey api”,
  “main”: “index.js”,
  “scripts”: {
    “start”: “nodemon index.js”
   },
  “author”: “Sihem BOUHENNICHE”,
  “license”: “ISC”,
  “dependencies”: {
    “express”: “⁴.18.2”,
    “mongoose”: “⁶.7.4”,
    “nodemon”: “².0.20”
   }
}
  • index.js: точка входа нашего API, она содержит приложение Express и объявление маршрутов:
// Import dependencies
const express = require(“express”);
const database = require(“./initdb.utils”);

// Create app instance
const app = express();

// Define JSON as return type
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Configure headers
app.use((req, res, next) => {
  res.setHeader(“Access-Control-Allow-Origin”, “*”);
  res.setHeader(“Access-Control-Allow-Methods”, “GET, POST, PUT, DELETE”);
  res.setHeader(“Access-Control-Allow-Headers”, “Content-Type”);
  res.setHeader(“Access-Control-Allow-Credentials”, true);
  next();
});

// DEFINE ROUTES
app.use(“/hello”, (req, res) => {
  res.status(200).json({ message: “Hello world !” });
});
app.use(“/surveys”, require(“./survey.routes”));

// This route will handle all the requests that are
// not handled by any other route handler. In
// this handler we will redirect the user to
// an error page with NOT FOUND message and status
// code as 404 (HTTP status code for NOT found)
app.all(“*”, (req, res) => {
  res.status(404).json({ error: “End point not found” });
});

// Handle database error
database.on(“error”, (error) => {
  console.log(“Connection error: — — — — — — — — — — — — — “);
  console.log(error);
  console.log(“ — — — — — — — — — — — — — — — — — — — — — — “);
});

// Start app after connecting to Database
database.once(“connected”, () => {
  console.log(“Database Connected”);
  
  const PORT = 3001;
  app.listen(PORT, () => console.log(“Server ready at 3001”));
});
  • initdb.js: содержит конфигурацию подключения к нашей базе данных.
const mongoose = require(“mongoose”);

const MONGO_HOST = “localhost”;
const MONGO_PORT = 27017;
const MONGO_DB_NAME = “surveydb”;
const MONGO_URL = `mongodb://${MONGO_HOST}:${MONGO_PORT}/${MONGO_DB_NAME}`;
const connectOptions = {
  useNewUrlParser: true,
};

mongoose.connect(MONGO_URL, connectOptions);
const database = mongoose.connection;

module.exports = database;
  • survey.model.js: содержит схему нашей модели опроса.
const mongoose = require(“mongoose”);

const SurveySchema = mongoose.Schema(
  {
    Name: String,
    OverallSatisfaction: String,
    Quality: Array,
    ValuedAtWork: String,
    Explanation: String,
    Feedback: String,
  },
  {
    timestamps: true,
    strict: false,
  }
);

module.exports = mongoose.model(“Survey”, SurveySchema);
  • survey.controller.js: содержит наши веб-службы. В нашем примере мы создадим только две службы: одну для сохранения результатов опроса, а другую для получения результатов.
const Survey = require(“./survey.model”);

// Create and Save a new Survey
exports.create = (req, res) => {
  const surveyData = req.body;

  // Create a Post
  const survey = new Survey(surveyData);

  // Save Post in the database
  survey
    .save()
    .then((data) => {
      res.send(data);
    })
    .catch((err) => {
      res.status(500).send({
      message:
        err.message || “Some error occurred while creating the survey.”,
    });
  });
};

// Find all surveys
exports.findAll = (req, res) => {
  Survey.find({})
    .then((data) => {
      res.send(data);
    })
    .catch((err) => {
      res.status(500).send({
        message: err.message || “Some error occurred while retrieving data.”,
      });
    });
};
  • survey.routes.js: содержит маршруты нашего API.
const surveyController = require(“./survey.controller”);
const router = require(“express”).Router();

//CRUD
router
  .post(“/”, surveyController.create)
  .get(“/”, surveyController.findAll);

module.exports = router;

Теперь давайте запустим наш API, выполнив следующую команду:

npm run start

Если вы перейдете на http://localhost:3001/hello, вы увидите сообщение hello world!

Если вы попробуете http://localhost:3001/surveys, вы получите пустой ответ, потому что опрос еще не сохранен.

В следующем разделе мы сохраним результаты с помощью нашего API.

Шаг 5: Сохраните результаты в коллекции MongoDB

Теперь, когда у нас есть API, давайте обновим файл app.component.ts и вместо того, чтобы просто записывать результаты опроса, будем отправлять их с помощью HTTP-запроса к нашему API.

import { Component, OnInit } from ‘@angular/core’;
import { Model, StylesManager } from ‘survey-core’;

// const SURVEY_ID = 1;

StylesManager.applyTheme(‘modern’);

const surveyJson = {
  …
};

@Component({
  selector: ‘app-root’,
  templateUrl: ‘./app.component.html’,
  styleUrls: [‘./app.component.css’],
})
export class AppComponent implements OnInit {
  title = ‘My First Survey’;
  surveyModel: Model;
  logSurveyResults(sender) {
    console.log(sender.data);
  }
  saveSurveyResults(sender) {
    const request = new XMLHttpRequest();
    const url = ‘<http://localhost:3001/surveys>';
    request.open(‘POST’, url);
    request.setRequestHeader(‘Content-Type’, ‘application/json;charset=UTF-8’);
    request.send(JSON.stringify(sender.data));
  }
  ngOnInit() {
    const survey = new Model(surveyJson);
    survey.onComplete.add(this.saveSurveyResults);
    this.surveyModel = survey;
  }
}

После этого и после заполнения всех полей, если мы нажмем кнопку завершения опроса, данные будут отправлены в API:

И, если вы сейчас попытаетесь зайти на http://localhost:3001/surveys, вы увидите результаты:

Заключение

На этом мы подошли к концу урока. Вы можете делать много других сложных вещей, используя Библиотеку форм SurveyJS. Это абсолютно бесплатно и с открытым исходным кодом, так что не стесняйтесь попробовать.

А чтобы узнать о других функциях, помимо бесплатной библиотеки форм, ознакомьтесь с разделом цен.

Полный код этого проекта можно найти здесь:

  • Ссылка на репозиторий приложения Angular на GitHub:


  • Ссылка на GitHub-репозиторий Express API:


Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .

Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.