Валидация AngularJS форм с ngMessages

angular
image-3100

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

Вывод сообщения без ngMessages

Давайте взглянем на то, как формы выглядят без использования этого модуля.

<form name="userForm">
    <input
        type="text"
        name="username"
        ng-model="user.username"
        ng-minlength="3"
        ng-maxlength="8"
        required>
    <!-- show an error if username is too short -->
    <p ng-show="userForm.username.$error.minlength">Username is too short.</p>
    <!-- show an error if username is too long -->
    <p ng-show="userForm.username.$error.maxlength">Username is too long.</p>
    <!-- show an error if this isn't filled in -->
    <p ng-show="userForm.username.$error.required">Your username is required.</p>
</form>

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

Быстрый взгляд на ngMessages

Давайте используем предыдущий пример и посмотрим, как это будет выглядеть с ngMessages.

<form name="userForm">
    <input
        type="text"
        name="username"
        ng-model="user.username"
        ng-minlength="3"
        ng-maxlength="8"
        required>
    <div ng-messages="userForm.name.$error">
        <p ng-message="minlength">Your name is too short.</p>
        <p ng-message="maxlength">Your name is too long.</p>
        <p ng-message="required">Your name is required.</p>
    </div>
</form>

Гораздо лучше. ngMessages будет обрабатывать, показывая и скрывая определенные сообщения, основанные на ошибках.

Использование ngMessages

Установить ngMessages очень просто. Нам просто нужно загрузить модуль после AngularJS и затем добавить его в нашем приложении.

Загрузка зависимости и добавление

<!-- load angular -->
<script src="//code.angularjs.org/1.4.0/angular.js"></script>
<!-- load ngmessages -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-messages.js"></script>
<!-- load our custom app -->
<script src="app.js"></script>

Теперь мы можем добавить в наше приложение в app.js.

angular.module('app', ['ngMessages']);

Отображение сообщений

Просто используйте директиву ng-messages и передайте в поле то что вы хотите увидеть при возникновении ошибки.
Формат использования:

<div ng-messages="<formName>.<inputName>.$error">
    <p ng-message="<validationName>">Your message here.</p>
</div>

Заключение

С помощью этого простого модуля, валидация форм AngularJS становится гораздо проще. Попробуйте его в ваших собственных приложениях и вы сами все поймете.

AngularJS маршрутизацию с помощью UI-Router

angular
image-985

AngularJS обеспечивает отличный способ сделать приложения на одной странице. При создании приложений на одной странице, маршрутизация будет очень важной.

Сегодня посмотрим на маршрутизацию с помощью UI-Router.

Обзор

Что такое AngularUI маршрутизатор?

UI-Router маршрутизация фреймворка для AngularJS созданная AngularUI командой. Она обеспечивает иной подход, чем ngRoute, и меняет, основанное на состояние приложения, а не только URL маршрута.

Состояния vs URL пути

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

При использовании ngRoute, вам придется использовать ngInclude или другие методы, и это может привести к путанице. Теперь, когда все ваши состояния, маршрутизации и виды обрабатываются в одном .config().

Простое приложение

Давайте создадим простое приложение. У нас будет две страницы Главная и О нас.

Установка

Нам понадобится несколько файлов:

- index.html                    // главный шаблон нашего приложения
- app.js                        // код angular приложения
- partial-about.html            // страница о нас
- partial-home.html             // главная страница
- partial-home-list.html        // вывод на главной странице
- table-data.html               // таблица

С нашей структура приложения выяснили, давайте перейдем к самим файлам.

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <!-- CSS (загрузка bootstrap) -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
    <style>
        .navbar { border-radius:0; }
    </style>
    <!-- JS (загрузка angular, ui-router) -->
    <script src="http://code.angularjs.org/1.2.13/angular.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
    <script src="app.js"></script>
</head>
<!-- app нашего приложения -->
<body ng-app="routerApp">
<!-- навигация -->
<nav class="navbar navbar-inverse" role="navigation">
    <div class="navbar-header">
        <a class="navbar-brand" ui-sref="#">AngularUI Router</a>
    </div>
    <ul class="nav navbar-nav">
        <li><a ui-sref="home">Главная</a></li>
        <li><a ui-sref="about">О нас</a></li>
    </ul>
</nav>
<!-- основной контент -->
<div class="container">
    <div ui-view></div>
</div>
</body>
</html>

Мы будем использовать Bootstrap, для стилизации наших страниц. Обратите внимание, что мы также загрузили ui-router. UI Router находится отделена от основного Angular ядра.

При создании связь с UI-Router, вы будете использовать ui-sref. Ссылки будет генерироваться из состояние вашего приложения и указывать на них. Они создаются в app.js.

Мы также используем

вместо

как в ngRoute.

Перейдем к нашему app.js.

// app.js
var routerApp = angular.module('routerApp', ['ui.router']);
routerApp.config(function($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise('/home');
    $stateProvider
        // главная, состояние и вид ========================================
        .state('home', {
            url: '/home',
            templateUrl: 'partial-home.html'
        })
        // о нас =================================
        .state('about', {
            // we'll get to this in a bit
        });
});

Теперь мы создали routerApp, что мы уже обратились к нашему body в index.html.

Здесь у нас .state() для страниц главная и о нас. На главной, мы используем файл шаблона partial-home.html.

Давайте заполним нашу страницу partial-home.html что бы мы смогли ее увидеть в приложении.

<!-- partial-home.html -->
<div class="jumbotron text-center">
    <h1>The Homey Page</h1>
    <p>This page demonstrates <span class="text-danger">nested</span> views.</p>
</div>

Теперь у нас есть наше приложение. Это не так уж много, но у нас это есть.

angular-ui-router-home-first[1]
image-986

Вложенные виды

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

Мы собираемся добавить наши кнопки в partial-home.html.

<!-- partial-home.html -->
<div class="jumbotron text-center">
    <h1>Главная страница</h1>
    <p>Эта страница показывает <span class="text-danger">вложенные</span> виды.</p>
    <a ui-sref=".list" class="btn btn-primary">Список</a>
    <a ui-sref=".paragraph" class="btn btn-danger">Абзац</a>
</div>
<div ui-view></div>

ui-sref=».list» и ui-sref=».paragraph» будут определены в нашей app.js и как только мы добавим их, мы сможем выводить информацию в

.

// app.js
...
$stateProvider
    // HOME STATES AND NESTED VIEWS ========================================
    .state('home', {
        url: '/home',
        templateUrl: 'partial-home.html'
    })
    // nested list with custom controller
    .state('home.list', {
        url: '/list',
        templateUrl: 'partial-home-list.html',
        controller: function($scope) {
            $scope.dogs = ['Bernese', 'Husky', 'Goldendoodle'];
        }
    })
    // nested list with just some random string data
    .state('home.paragraph', {
        url: '/paragraph',
        template: 'I could sure use a drink right now.'
    })
...

Теперь ui-sref мы определили в home.html, связаны с фактическим состоянием. С home.list и home.paragraph создали, эти ссылки будут теперь принимать предоставленный шаблон и ввести его в ui-view.

Последнее, что нам нужно сделать для домашней странице определить файл partial-home-list.html.

<!-- partial-home-list.html -->
<ul>
    <li ng-repeat="dog in dogs">{{ dog }}</li>
</ul>

Теперь мы получаем следующее приложение со вложенными страницами.

angular-routing-ui-router-home-list[1]
image-987

Вывод

Это небольшой обзор отличный инструмент UI-Router. То, что вы можете делать с ним невероятные и когда вы смотрите на ваше приложения как на состояния, Angular приложения могут быть легко созданы, чтобы быть модульными и расширяемыми.

Сортировка и фильтрация таблицы с помощью Angular

angular
image-957

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

7661

Простое приложение

Наше приложение позволит нам:

  • Вывести таблицу данных (ng-repeat)
  • Сортировать по возрастанию или по убыванию колонки (orderBy)
  • Фильтр с помощью поля поиска (filter)

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

Настройки

Что мы будем использовать?

Bootstrap and Font Awesome для стилизации нашего приложение, и конечно же AngularJS. У нас будет два файла:

- index.html
- app.js

Вот код app.js:

angular.module('sortApp', [])
.controller('mainController', function($scope) {
  $scope.sortType     = 'name'; // значение сортировки по умолчанию
  $scope.sortReverse  = false;  // обратная сортировка
  $scope.searchFish   = '';     // значение поиска по умолчанию
  // список
  $scope.sushi = [
    { name: 'Cali Roll', fish: 'Crab', tastiness: 2 },
    { name: 'Philly', fish: 'Tuna', tastiness: 4 },
    { name: 'Tiger', fish: 'Eel', tastiness: 7 },
    { name: 'Rainbow', fish: 'Variety', tastiness: 6 }
  ];

Тут у нас приложение sortApp и его контроллер mainController. Инициализируем три переменные: sortType, sortReverse, searchFish. Так же мы создали объект список суш. Теперь используем этот модуль в нашем HTML шаблоне:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Angular Sort and Filter</title>
    <!-- CSS -->
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootswatch/3.2.0/sandstone/bootstrap.min.css">
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css">
    <style>
        body { padding-top:50px; }
    </style>
    <!-- JS -->
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script src="app.js"></script>
</head>
<body>
<div class="container" ng-app="sortApp" ng-controller="mainController">
  <div class="alert alert-info">
    <p>Sort Type: {{ sortType }}</p>
    <p>Sort Reverse: {{ sortReverse }}</p>
    <p>Search Query: {{ searchFish }}</p>
  </div>
  <table class="table table-bordered table-striped">
    <thead>
      <tr>
        <td>
            Sushi Roll
        </td>
        <td>
          Fish Type
        </td>
        <td>
          Taste Level
        </td>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="roll in sushi">
        <td>{{ roll.name }}</td>
        <td>{{ roll.fish }}</td>
        <td>{{ roll.tastiness }}</td>
      </tr>
    </tbody>
  </table>
</div>
</body>
</html>

Мы используем ngRepeat для вывода суши, которые мы создали в нашем модуле. Наше приложение теперь будет выглядеть следующим образом:

43b4-Z6AOUg
image-958

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

Сортировка таблицы

Мы будем достигать этой сортировки используя две переменные, которые мы создали ранее ($scope.sortType и $scope.sortReverse). Мы также будем использовать Angular фильтр orderBy. В принципе, используя сочетание переменных sortType и sortReverse к orderBy в нашем ng-repeat таблица будет от сортирована.

<!-- index.html -->
...
    <tr ng-repeat="roll in sushi | orderBy:sortType:sortReverse">
...

Это все, что нужно, чтобы изменить порядок сортировки нашего ng-repeat. Если вы обновите страницу, то увидите, что список отсортирован по называют в обычном порядке. Если вы измените в модуле параметры по умолчанию на $scope.sortType = 'fish' или $scope.sortReverse = true; то и сортировка изменится, сортировка будет теперь по полю fish и в обратном порядке.

Создание кликабельных заголовков таблицы

Мы добавим ссылки в наши заголовки таблицы. Давайте посмотрим на thead тег нашего сайта и используем ng-click, чтобы настроить переменную sortType:

...
    <thead>
      <tr>
        <td>
          <a href="#" ng-click="sortType = 'name'">
            Sushi Roll
            <span ng-show="sortType == 'name'" class="fa fa-caret-down"></span>
          </a>
        </td>
        <td>
          <a href="#" ng-click="sortType = 'fish'">
          <span ng-show="sortType == 'fish'" class="fa fa-caret-down"></span>
          Fish Type
          </a>
        </td>
        <td>
          <a href="#" ng-click="sortType = 'tastiness'">
          <span ng-show="sortType == 'tastiness'" class="fa fa-caret-down"></span>
          Taste Level
          </a>
        </td>
      </tr>
    </thead>
...

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

Изменение порядка сортировки

Следующим шагом будет добавление возможности изменять направление сортировки, так что бы пользователи могли сортировать таблицу по возрастанию или по убыванию. У фильтра orderBy есть третий параметр reverse. Мы просто должны передать true или false, чтобы изменить порядок сортировки. Сейчас значение false, так как мы инциализировали переменную $scope.sortReverse. Мы добавим возможность менять направление сортировки:

...
    <a href="#" ng-click="sortType = 'name'; sortReverse = !sortReverse">
...

Теперь, если вы кликните по заголовку, вы увидите изменение порядка сортировки. Давайте добавим знак направления сортировки, для большей наглядности. Мы добавим иконки вверх и вниз, а затем использовать ngShow и ngHide, чтобы показать и скрыть их. Вот как будет выглядеть одна из ссылок:

...
    <td>
      <a href="#" ng-click="sortType = 'name'; sortReverse = !sortReverse">
        Sushi Roll
        <span ng-show="sortType == 'name' && !sortReverse" class="fa fa-caret-down"></span>
        <span ng-show="sortType == 'name' && sortReverse" class="fa fa-caret-up"></span>
      </a>
    </td>
...

Фильтрация таблицы

Фильтрация данных в ng-repeat довольно легко, так как у Angular есть модуль фильтра. Есть только две вещи, которые мы должны сделать здесь: создать форму и применить переменную формы в ng-repeat. Давайте создадим форму:

  <form>
    <div class="form-group">
      <div class="input-group">
        <div class="input-group-addon"><i class="fa fa-search"></i></div>
        <input type="text" class="form-control" placeholder="Search da Fish" ng-model="searchFish">
      </div>
    </div>
  </form>

Это обычная Bootstrap форма. Основное тут это ng-model="searchFish" нашего input. searchFish мы будем использовать при фильтрации:

<!-- index.html -->
...
    <tr ng-repeat="roll in sushi | orderBy:sortType:sortReverse | filter:searchFish">
...

Так наш фильтр будет применен к таблице. Вы также заметите, что orderBy и filter будет работать вместе.

7661

Вывод.

Используя встроенные инструменты Angular, такие как ngRepeat, OrderBy, filter, ngClick и ngShow, мы смогли создать функциональную и быструю таблицу данных. Это один из примеров, когда Angular помогает в создании некоторой функциональности в приложения без лишних затрат.

Основы AngularJS (шпаргалка) Часть 1

angular[1]
image-885

Настройка и установка

Устанавливать будем с помощью bower, так как ним очень удобно устанавливать дополнения для angular. Настройка каталога для .bowerrc (настройка не обязательная, я использую для смены стандартной директории установки компонентов)

{
  "directory": "components/",
  "analytics": false,
  "timeout": 120000,
  "registry": {
    "search": [
      "http://localhost:8000",
      "https://bower.herokuapp.com"
    ]
  }
}

Инициализация bower и установка angular с сохранением в конфигурации

bower init
bower install angular --save

Подключаем к шаблону.

<html ng-app>
 <head>
 </head>
 <body>
   //основная часть с директивами angular
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/script.js"></script>
   </body>
</html>

Обертка

{{ 'Привет' }}
{{ 'Привет' + myVar }}
{{ 3 + 5 }}
<input type="text" ng-model="data.message">
<h1>{{ data.message }}</h1>

Контроллер

Добавляем в шаблоне директивы ng-app и ng-controller

<html ng-app="myApp">
 <head>
 </head>
 <body ng-controlle="FirstCtrl">
   <input type="text" ng=model="data.message">
   <h1>{{ data.message }}</h1>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

main.js

var app = angular.module('myApp', [])
app.controller('FirstCctrl', function($scope){
   $scope.data = {message:'Hello'}
});

Обмен данными между контроллерами

Создаем два контроллера FirstCtrl и SecondCtrl.

<html ng-app="myApp">
 <head>
 </head>
 <body>
	<div ng-controller="FirstCtrl">
	    <h1>{{ data.message }}</h1>
	</div>
	<div ng-controller="SecondCtrl">
	    <h1>{{ data.message }}</h1>
	</div>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

main.js

var app = angular.module('myApp', []);
app.factory('Data', function(){
	return {message: 'Message'}
});
app.controller('FirstCtrl', function ($scope, Data){
	$scope.data = Data
});
app.controller('SecondCtrl', function($scope, Data){
	$scope.data = Data
});

Добавление методов в scope

Добавим новый метод reversedMessage() (он будет переворачивать текст)

<html ng-app="myApp">
 <head>
 </head>
 <body>
	<div ng-controller="FirstCtrl">
	    <h1>{{ data.message }}</h1>
            <h3>{{ reversedMessage() }}</h3>
	</div>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

main.js

var app = angular.module('myApp', []);
app.controller('FirstCtrl', function ($scope){
	$scope.data = {message: 'Привет'};
	$scope.reversedMessage = function(){
            return $scope.data.message.split("").reverse().join("");
	}
});

Фильтр

Добавим фильтр reverse который будет делать то же самое что и предыдущий метод

<html ng-app="myApp">
 <head>
 </head>
 <body>
	<div ng-controller="FirstCtrl">
	    <h1>{{ data.message }}</h1>
            <h3>{{ data.message|reverse }}</h3>
	</div>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

main.js

var app = angular.module('myApp', []);
app.filter('reverse', function(Data){
	return function(text){
		return text.split("").reverse().join("") + " " + Data.message;
	}
});
app.controller('FirstCtrl', function ($scope){
	$scope.data = {message:'Текст'};
});

ngFiltr

В main.js создадим объект Avengers

var app = angular.module('myApp', []);
app.factory('Avengers', function () {
    var Avengers = {};
    Avengers.cast = [
        {
            name: 'Roma',
            character: 'Rdfvbbdf'
        },
        {
            name: 'Sasha',
            character: 'SDFSDffsdfsd'
        },
        {
            name: 'Tanya',
            character: 'Sdfvds'
        }
    ];
    return Avengers;
});
app.controller('AvengersCtrl', function($scope, Avengers){
    $scope.avengers = Avengers;
});

Выводим в таблице все значения и фильтруем их с помощью search.

<html ng-app="myApp">
 <head>
 </head>
 <body>
        <div ng-controller="AvengersCtrl">
            <input type="text" ng-model="search"/>
            <table>
                <tr ng-repeat="actor in avengers.cast | filter: search">
                    <td>{{ actor.name }}</td>
                    <td>{{ actor.character }}</td>
                </tr>
            </table>
        </div>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

Так же можно фильтровать только по name(ng-model="search.name"), по character(ng-model="search.character") или по обоим сразу(ng-model=»search.$»)

Встроенные фильтры

В main.js без изменений

var app = angular.module('myApp', []);
app.factory('Avengers', function () {
    var Avengers = {};
    Avengers.cast = [
        {
            name: 'Roma',
            character: 'Rdfvbbdf'
        },
        {
            name: 'Sasha',
            character: 'SDFSDffsdfsd'
        },
        {
            name: 'Tanya',
            character: 'Sdfvds'
        }
    ];
    return Avengers;
});
app.controller('AvengersCtrl', function($scope, Avengers){
    $scope.avengers = Avengers;
});

Выводим в таблице все значения и фильтруем их с помощью search.

<html ng-app="myApp">
 <head>
 </head>
 <body>
        <div ng-controller="AvengersCtrl">
            <input type="text" ng-model="search"/>
            <table>
                <tr ng-repeat="actor in avengers.cast | orderBy: 'name'">
                    <td>{{ actor.name }}</td>
                    <td>{{ actor.character }}</td>
                </tr>
            </table>
        </div>
   <script src="/путь/до/angular.js"></script>
   <script src="/путь/до/main.js"></script>
   </body>
</html>

Отсортирует по полю name. Возможные варианты:

orderBy: 'name' сортировка по полю name
orderBy: '-name' обратная сортировка по полю name
limitTo:5 первые пять элементов
limitTo:5 последние пять элементов
orderBy: 'name' | limitTo:5 | filter:search несколько фильтров одновременно

Вывод относительного времени в Angular

angular
image-906

Вывод относительного времени стало популярным в последние несколько лет. Это можно увидеть в социальных сетях, таких как Twitter, Facebook и vk.

Например, вместо того, чтобы отображать время записи, как 8:12, время будет отображаться как 3 часа назад.

Это помогает пользователям видеть относительное время и облегчает понимание, как давно было обновление. Мы посмотрим как мы можем достичь этого эффекта в Angular.

Пакеты

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

Пакет, который поможет нам отображать относительное время — angular-moment. Этот пакет использует библиотеку MomentJS. Если вы не использовали библиотеку раньше, посмотрите ее; она может помочь со всеми видами скриптов, в которых вам приходится работать с датой и временем в JavaScript.

Установка

Есть несколько способов установки этого пакета. В этой статье мы просто подключим через CDNJS.

Все, что мы должны сделать, это добавить следующие строки в нашем проекте:

<!-- подключаем angular -->
<script src='//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js'>
<!-- загрузка momentJS (необходим для angular-moment) -->
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment.min.js"></script>
<!-- загрузка angular-moment -->
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-moment/0.9.0/angular-moment.min.js"></script>
<!-- подключаем языковой файл vjventjs, нужен для русского языка -->
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/locales.js"></script>

Модель

А нас будет следующий код модуля:

// создание angular приложения
angular.module('timeApp', ['angularMoment'])
// создание angular контроллера
.controller('mainController', function() {
  // связь контроллера с vm (вид-модель)
  var vm = this;
  //устанавливаем русский язык
  moment.locale('ru');
  // создание новой временной переменной с текущей датой
  vm.time = new Date();
});

Мы создали новую переменную времени с использованием new Date(). Вы можете передать дату и время в Date(), чтобы конвертировать ее в объект даты. Наши данные и Angular приложение готово, теперь перейдем к HTML разметке, чтобы увидеть, как мы можем вывести переменную vm.time для наших пользователей.

Вид

Мы должны применить Angular модуль (timeApp) и контроллер (mainController) в нашем приложении:

<!-- добавим наше приложение(модуль) и контроллер-->
<div class="container" ng-app="timeApp" ng-controller="mainController as main">
  <div class="jumbotron">
    <p>Время: {{ main.time }}</p>
  </div>
</div>

7661

С начало мы просто выведем время. Основные способы, которые мы можем использовать в этом пакете являются директивы и фильтры. Давайте их посмотрим.

Методы использования этого пакета

Относительное время — Директива

<time am-time-ago="main.time"></time>

Директива am-time-ago будет автоматически обновлять значение времени. Когда вы первый раз увидите ее, вы увидите несколько секунд назад. Если вы подождете, вы увидите 3 минут назад и тд.

В дополнение к использованию директивы, у нас также есть возможность использовать фильтр при отображении времени.

Формат даты — Фильтр

При использовании фильтра, можно вывести точный формат, который вам нужен:

<time>{{ main.time | amDateFormat: 'dddd, MMMM Do YYYY, h:mm a' }}</time>

Календарный Формат — Фильтр

Третий способ, которым вы можете использовать это календарный формат.

Календарный формат будут отображать различные строки на основе того, насколько близко дата к определенному времени.

<time>{{ main.time | amCalendar }}</time>

Хорошая практика

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

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

<time title="{{ main.time | amDateFormat: 'dddd, MMMM Do YYYY, h:mm a' }}">{{ main.time | amCalendar }}</time>

Демо

7661

Вывод

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

Защита маршрутов в AngularJS

angular
image-879

Если у вас есть какие-то маршруты в AngularJS, которые вы хотите защитить от не авторизованных пользователей, просто создайте функцию, которая будет перенаправлять пользователей на страницу входа, если он не авторизован.

var loginRequired = function($location, $q) {
    var deferred = $q.defer();
    if(! userIsAuthenticated()) {
        deferred.reject()
        $location.path('/login');
    } else {
        deferred.resolve()
    }
    return deferred.promise;
}

И добавьте эту функцию, в маршруты которые требуется проверка подлинности

app.config(['$locationProvider', '$routeProvider',
    function($location, $routeProvider) {
        $routeProvider.
            when('/todos', {
                templateUrl: '/js/templates/todos/index.html',
                controller: 'TodoCtrl',
                resolve: { loginRequired: loginRequired }
            });
    }
]);

Если вам нужно, чтобы пользователь автоматически перенаправляться на урл после авторизации:

var redirectIfAuthenticated = function(route) {
    return function($location, $q) {
        var deferred = $q.defer();
        if (userIsAuthenticated()) {
            deferred.reject()
            $location.path(route);
        } else {
            deferred.resolve()
        }
        return deferred.promise;
    }
}
app.config(['$locationProvider', '$routeProvider',
    function($location, $routeProvider) {
        $routeProvider.
            when('/login', {
                templateUrl: '/js/templates/login.html',
                controller: 'UserCtrl',
                resolve: { redirectIfAuthenticated: redirectIfAuthenticated('/todos') }
            }).
            when('/todos', {
                templateUrl: '/js/templates/todos/index.html',
                controller: 'TodoCtrl',
                resolve: { loginRequired: loginRequired }
            });
    }
]);

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

Языки и фреймворки, которые вы должны изучить в 2015м году

Языки / платформы

Node.js является победителем в этом списке,  PHP второй, и JavaScript — третий. Существует большое сообщество вокруг Node.js, так что это не удивительно. Если вы знаете JavaScript, вы уже наполовину способны к создания веб-приложений в Node.js.

Фреймворки

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

Чтобы помочь вам сделать свой выбор, ниже небольшой обзор из вышеперечисленных технологий!

Вот то, чему вы должны научиться в 2015 году

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

1. JavaScript везде

офмфыскшзе
image-323

Если вы занимаетесь веб-разработкой, JavaScript является языком, который вы должны знать, независимо от того, какой язык программирования используете. Сегодня вы можете использовать JS в браузере, на сервере, в мобильных приложениях и даже на программируемом оборудовании. ES6 принесет необходимых улучшений и сделает язык еще более мощным и легко в написании. Это также хорошая идея, чтобы узнать о Bower и npm, а также инструменты, такие как jshint и jscs.

2. AngularJS

angular
image-324

AngularJS является JavaScript фреймворком от Google, который быстро зарекомендовал себя как инструмент для создания мощных веб-приложений. При этом признании приходит повышенный спрос на программистов умеющих работать с ним, по этому вы найдете упоминание о нем в списке требований почти в каждом вакансии JavaScript разработчика. Причин не изучать его просто нет.

3. React

react
image-325

React является новичком в этом списке. Библиотека разработана Facebook и обеспечивает очень быструю работу благодаря производительности своей виртуальной DOM, и может быть легко подключен в существующие проекты. Она также имеет очень активное сообщество, которое развивается все виды компонентов. На наш взгляд, React имеет большой потенциал и является фреймворком, который стоит чтобы посмотреть (и учить) в 2015 году.

4. Node.js

nodejs
image-326

С Node.js вы можете разрабатывать сетевые серверные приложения на JavaScript. Он может быть использован для простых движков веб-сайтов с использованием такой структуры, как Express, конечных точек API, WebSocket серверов или даже торрент-клиентов. Node имеет невероятно активное сообщество и превысил всех других языков по количеству модулей в этом году.

5. NoSQL databases

nosql
image-327

Базы данных, которые не нужны ни таблицы, ни SQL высоко ценятся современные веб-разработчики, и мы считаем, что эти базы данных станут только более популярным в следующем году. Два примечательных варианты MongoDB и Redis. Это гораздо проще начать с одного из этих баз данных, чем с MySQL и Postgres. Но не ведитесь, думая, что базы данных NoSQL являются идеальной заменой — в некоторых ситуациях классический реляционная база данных сделает ваше развитие легче даже если это займет больше усилий.

6. Less/Sass/Stylus

lesscss
image-328

Существует много что не нравится в CSS. Это слишком просто, в конечном итоге получаются громоздкие файлы с 1000 линиями, который трудно ориентироваться и измененять. Чтобы решить эту проблему, есть языки, такие как Less, Sass и Styles, которые составляются для CSS и предлагают переменные, макросы и другие вкусности, которые помогут вам улучшить ваш код. Вы можете изучить один из них за один день.

7. Потрясающие новые фреймворки

exciting-new-frameworks
image-329

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

8. Потрясающие новые языки

exciting-new-languages
image-330

Для языковых ботаников, вот некоторые новые языки. Golang, Rust и Elixir набирают обороты в программировании и используются в ситуациях, когда требуется очень высокая производительность.

9. Классические популярные фремворки

full-stack-frameworks
image-331

Несмотря на то что одностраничные приложения набирает популярность, до сих пор огромный спрос имеют на классические серверных веб-приложения. Ruby on Rails, Django, Laravel, Play, ASP.NET являются наиболее популярными фреймворками в данный момент.

10. Старая гвардия

the-old-guard
image-332

Существует большая коллекция установленных языков и платформ, которые по-прежнему востребованы — Java, .NET, Python, Ruby. Они имеют большие сообщества и будет хорошо смотреться в любом резюме. Все они имеют свои плюсы и минусы.

Валидация формы на AngularJS и отправка на Ajax

Очень простой способ валидации формы на AngularJS, который создается и настраивается за пару минут. Что будем делать:

  1. Создадим форму заявки обратного звонка
  2. Не правильно заполненные поля будет подсвечиваться в режиме реального времене
  3. Проверим форму на валидность
  4. Отправим все данный на сервер(ajax.php)
  5. Проверим данные, отправим сообщение если все ок, иначе вернем ошибку

0) Подключение необходимых библиотек

Мы будем использовать не только ангуляр но и библиотеку ангуляра ui-utils

 <script type="text/javascript" src="js/angular.min.js"></script>
 <script type="text/javascript" src="js/ui-utils.min.js"></script>

Это все библиотеку которые нам понадобятся

1) Создание формы

Вот готовая форма:

<div ng-app="test-app">
  <form action="" ng-controller="ctrlForm" name="form" ng-submit="submit()">
    <input type="text" placeholder="ИМЯ" ng-model="user.name" required>
    <input type="text" ng-model="user.phone" ui-mask="+7 (999) 999-99-99" required>
    <input type="email" placeholder="E-MAIL" ng-model="user.email">
    <input type="submit" class="btn red" value="Отправить">
  </form>
</div>

ng-app="test-app" — это название нашего приложения на angularJS, все контроллеры этого приложения должны быть внутри него. Обычно я его вешаю на body.

ng-controller="ctrlForm" — это название нашего контролера

name="form" — как ни странно название нашей формы, почему это важно будет понятно в контроллере ctrlForm

ng-submit="submit()" — название функции в контроллере которая будет обрабатывать данные

ng-model="user.name" — название модели. Все данные будут хранится в объекте user.

ui-mask="+7 (999) 999-99-99" — маска для телефона, ради этой строчки мы и подключили ui-utils.min.js

2-4) Пункты отдельные но все будет в одном js, в одном контроллере

Но для начала строчка css

form .ng-dirty.ng-invalid{
  border: 1px solid #FD0000;
}

.ng-dirty.ng-invalid поля формы будут подсвечивать если dirty — тронуты, invalid — невалидны

Ну и главный код

'use strict';
var app = angular.module('test-app', ['ui.utils']);
app.controller('ctrlForm',function($scope, $http) {
    $scope.user = {};
    $scope.submit = function() {
        if ( $scope.form.$valid ) {
            $http.post( 'ajax.php', $scope.user ).success(function( res ){
                if ( res.res=='ok') {
                    $scope.user = {};
                    $scope.form.$setPristine();
                    alert('Сообщение отправлено');
                } else {
                    alert('Возникла ошибка');
                }
            }).error(function(err){
                alert(err);
            });
        }
    }
});

Если вкратце: включаем строгий режим(use strict), создаем наше приложение и подключаем к нему ui.utils, создаем наш контроллер, создаем объект user, создаем функцию submit, проверяем нашу форму на валидность($scope.form.$valid), вот здесь form это название нашей формы(name="form"), если форма валидна отправляем данные($scope.user) в ajax.php.

ajax.php:

$req = json_decode( file_get_contents('php://input'), true );
//подключаем класс для работы с email
require 'class.simple_mail.php';
if ( $req ) {
	//отправляем данные с помощью функции mail
	if (!empty($req['name'])) $name = $req['name'];
	if (!empty($req['phone'])) $phone = $req['phone'];
	if (!empty($req['email'])) $email = $req['email'];
	if (!empty($name) && !empty($phone) && !empty($types)) {
		//формируем сообщение и отправляем
		$mes = "Имя: " .$name . "\nТелефон: ".$phone;
		if (!empty($email)) $mes .= "\nEmail: ".$email;
		$mail = new SimpleMail();
		$mail->setTo('mail@domen.ru', 'Your Email')
		     ->setSubject($types)
		     ->setFrom('admin@domen.ru', 'domen.ru')
		     ->setMessage($mes)
		     ->setWrap(100);
		$send = $mail->send();
		if ($send) {
			$res = array( 'res'=>'ok' );
		 	echo json_encode($res);
		}else{
			$res = array( 'res'=>false, 'msg'=>'Error!' );
			echo json_encode($res);
		}
	}else{
		//поля не заполнены
		$res = array( 'res'=>false, 'msg'=>'Заполните все поля.' );
		echo json_encode($res);
	}
} else {
	$res = array( 'res'=>false, 'msg'=>'Заполните все поля.' );
}

Весь пример целиком(кроме ajax.php)

7661