Содержание:
- Введение
- Почему именно SurveyJS?
- Создание опроса
- Настройка проекта Angular
- Установка и настройка SurveyJS
- Создание опроса удовлетворенности сотрудников
- Настройка базы данных MongoDB
- Сохранение результатов в коллекции MongoDB
Введение
Опросы удовлетворенности полезны как для самих сотрудников, так и для работодателей.
В первом случае они показывают, что начальство принимает во внимание интересы подопечных и ценит их. Таким образом, повышается моральный дух и растет удовлетворенность работой.
Во втором случае опросы удовлетворенности могут предоставить ценную информацию как о том, с чем у компании все в порядке, так и о проблемных моментах, нуждающихся в исправлении. В результате работодатель принимает обоснованные решения, касающиеся поддержки своих сотрудников и улучшения общей рабочей атмосферы.
Удовлетворенные сотрудники отличаются высокой продуктивностью. Они по-настоящему вовлечены в работу, что приводит к повышению создаваемой коммерческой ценности. И наоборот, если в организации есть неудовлетворенные сотрудники, прибыльность бизнеса будет падать. Так что полезно всегда быть в курсе, и в этом помогут внутренние опросы работников.
В этой статье мы расскажем, как создать подобный опрос. Но прежде рассмотрим технологии, которые будем использовать.
- Angular: фреймворк для проектирования приложений и платформа для создания одностраничных приложений.
- SurveyJS: бесплатный конструктор форм на JavaScript с открытым исходным кодом (ссылка на Github), который упрощает создание форм на собственном сервере.
- MongoDB: документная база данных. Классифицируется как база данных типа NoSQL. MongoDB использует JSON-подобные документы с опциональными схемами.
Кто-то может возразить: хоть Angular и является предпочтительным корпоративным фреймворком, с его помощью разработчику не так-то легко создавать анкеты, которые хорошо масштабируются при наличии в них множества вопросов. Но в этой статье мы покажем элегантный способ разработки корпоративного опроса с помощью Angular, в котором не нужно использовать пары ngIf и ng-template для каждого вопроса, а также лишние привязки.
На помощь нам придет SurveyJS. С помощью этой библиотеки с открытым исходным кодом можно упростить создание форм и работу с ними в динамическом режиме. Рассмотрим это более подробно ниже, а пока разберемся, какие вопросы мы поместим в анкету.
Они подробно указаны в таблице ниже:
Анкета удовлетворенности сотрудников будет включать различные вопросы. Так мы определим, удовлетворены ли сотрудники работой в компании, а если нет, то почему.
В следующем разделе мы рассмотрим, почему используем SurveyJS в качестве инструмента для создания опроса.
Почему именно SurveyJS?
Следующие доводы красноречиво показывают, почему стоит использовать SurveyJS в сочетании с Angular для решения этой задачи, вместо того чтобы разрабатывать формы/опросы вручную с помощью примитивов Angular.
- Создание опросов на собственном сервере. Мы можем защитить данные и хранить их в выбранной базе данных, а не использовать сторонние онлайн-сервисы, как, например, Google Формы, которые хранят результаты в файлах Google Таблиц.
- Возможность легко создавать сложные опросы, включающие условную логику и ветвление. Мы также можем делать формы более развернутыми и адаптированными ко многим случаям использования без необходимости встраивать дополнительный 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 поставляется с 2 таблицами стилей: 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 называется схемой.
Например, эта простая схема содержит один вопрос, объявленный в массиве элементов:
const surveyJson = {
elements: [ // каждый элемент содержит вопрос
{
name: ‘Name’,// имя поля
title: ‘Enter your full name:’,// название поля
type: ‘text’,// тип поля
},
],
};
Затем создадим модель, передав схему в конструктор 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:
radiogroup
. - Матрица компонентов 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, автоматически перезапуская приложение node при обнаружении изменений файлов в каталоге.
- 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 и объявление маршрутов:
// Импорт зависимостей
const express = require(“express”);
const database = require(“./initdb.utils”);
// Создание экземпляра приложения
const app = express();
// Определение JSON в качестве типа возвращаемого значения
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Настройка заголовков
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();
});
// Определение маршрутов
app.use("/hello", (req, res) => {
res.status(200).json({ message: "Hello world !" });
});
app.use("/surveys", require("./survey.routes"));
// Этот маршрут будет обрабатывать все запросы, которые
// не обрабатываются никаким другим обработчиком маршрутов. С
// помощью этого обработчика мы перенаправяем пользователя на
// страницу ошибки с сообщением NOT FOUND и кодом
// состояния 404 (код состояния HTTP для NOT found).
app.all("*", (req, res) => {
res.status(404).json({ error: "End point not found" });
});
// Обработка ошибок базы данных
database.on("error", (error) => {
console.log("Connection error: - - - - - - - - - - - - - ");
console.log(error);
console.log(" - - - - - - - - - - - - - - - - - - - - - - ");
});
// Запуск приложения после подключения к базе данных
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
содержит веб-сервисы. В этом примере мы создадим только 2 сервиса — для сохранения и получения результатов.
const Survey = require(“./survey.model”);
// Создание и сохранение нового опроса
exports.create = (req, res) => {
const surveyData = req.body;
// Создание запроса POST
const survey = new Survey(surveyData);
// Сохранение запроса POST в базе данных
survey
.save()
.then((data) => {
res.send(data);
})
.catch((err) => {
res.status(500).send({
message:
err.message || "Some error occurred while creating the survey.",
});
});
};
// Находим все опросы
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, то увидите результаты:
Полный код этого проекта можно найти по следующим ссылкам.
Читайте также:
- Собеседование по Angular: ответы на часто задаваемые вопросы
- 15 идей для вашего приложения. Часть 3
- Типы операций обновления в MongoDB с использованием Spring Boot
Читайте нас в Telegram, VK и Дзен
Перевод статьи Sohom Das: Create Employee Satisfaction Survey Using Angular + MongoDB