Статья про Angular и Битрикс d7 Сейчас проходит
олимпиада (
http://academy.1c-bitrix.ru/konkurs/ ) Битрикс по разработке сайтов. Если посмотрим на
тестовое задание (
http://academy.1c-bitrix.ru/konkurs/s...index.html ), то мы увидим под капотом не jQuery, а
AngularJS (
http://angularjs.org/ ). Давайте рассмотрим преимущества данного фреймворка. Посмотрим как можно его использовать в своих проектах, как связать его с данными сайта и немного расширим свои знания
Итог посмотреть результат можно
тут (
http://onepage.bx-shef.by/article-ang...ar-bitrix/ )
Вся суть
ангуляра (
http://angular.ru/misc/faq ) сводится к двунаправленной связке данных из js и их представлением на странице. Прибавим сюда директивы (
http://angular.ru/guide/directive ), промисы/
promise (
http://angular.ru/api/ng.$q ) и
тестирование (
http://angular.ru/guide/dev_guide.unit-testing ). В итоге эта махина действительно становится Супер-героическим фреймворком для веб-приложений от компании google.
Давайте на пример разберем работу.
Задача:
вывести список пользователей
сделать по фильтр (имя, фамилия)
сделать карточку пользователя
Все это показать адаптивно и симпатично.
Для решения задачи будем использывать:
bootstrap (http://getbootstrap.com/ )
AngularJS (http://angularjs.org/ )
Bitrix D7 (http://dev.1c-bitrix.ru/learning/cour...=3913.5062 )
Начнем с шаблона За основу возьмем пример
Narrow jumbotron (
http://getbootstrap.com/examples/jumb...on-narrow/ )
Преобразуем и получим:
Исходный код страницы (
https://bel.bitrix24.ru/docs/pub/20ef8...index.html )
Теперь добавим ангуляр подключаем JS
....
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular-route.min.js"></script>
<script src="lib/angular/ui-bootstrap-tpls-0.10.0.min.js"></script>
</body>
указываем зависимости
angular.module('demo.shef', [
'ngRoute',
'ui.bootstrap'
])
расставим связки на страницы
* название приложения
<html lang="ru" ng-app="demo.shef">
* контент заменим на "включаемую область"
<div class="content">
<div ng-view ><div>
</div>
* расставим правила обработки адресов
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/list', {templateUrl: 'partials/list.html', controller: 'ListCtrl'});
$routeProvider.when('/user/:id', {templateUrl: 'partials/user.html', controller: 'UserCtrl'});
$routeProvider.otherwise({redirectTo: '/list'});
}])
* застолбим обработчики данных
.controller('ListCtrl', ['$scope', '$log', function($scope, $log) {
}])
.controller('UserCtrl', ['$scope', '$log', function($scope, $log) {
}])
Разнесем контент (шаблоны контента) по двум файлам partials/list.html и partials/user.html
Ангуляр сам их загрузит когда нужно будет
Для тестирования укажем ссылки:
* в списке
<tr>
<td><a href="#/user/1">1</a></td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
* и в карточке соответственно
<ul class="pager">
<li class="previous"><a href="#/list">← К списку</a></li>
</ul>
Исходный код (
https://bel.bitrix24.ru/docs/pub/66bbf...step_2.zip ) стоит смотреть на сервере (можно локальном)
Теперь посмотрим на d7 Создадим модуль.
В папку /local/modules/ положим эту
болванку (
https://bel.bitrix24.ru/docs/pub/25a27.../local.zip )
И устанавливаем его в системе /bitrix/admin/partner_modules.php?lang=ru
Чуть подробнее об модуле.
файл /local/modules/shef.def/admin/controller.php Контроллер. Принимает запрос от клиента, проверяет сессию, и подключает нужный класс для обработки запроса.
Т.е. вы через запрос шлете get('\Shef\Def\Project\Users::getUsers') - а контроллер сам подключит нужный php класс (\Shef\Def\Project\Users) и сам вызовет нужный статический метод (getUsers)
Так же присутствует проверка на namespace, что бы лишнего не дергали ))
if(stristr($_REQUEST['param1'][0], 'Shef') === false) ...
файл /local/modules/shef.def/lib/response.php Класс для формирования ответов клиенту. Он из массива формирует JSON нужного формата и отправляет
файл /local/modules/shef.def/lib/project/users.php Собственно класс, который нам возвращает список пользователей.
Суть структуры. Писать запрос к нужным классам в определенном (стандартном) формате. Это позволяет масштабировать решение для любых потребностей (выборка, внесение данных и т.п.)
Теперь соединим Ангуляр и наш модуль Переименуем index.html в index.php и добавим служебную часть эпилога и пролога на страницу. И в параметр запишем sessid пользователя
<?require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");?>
<!DOCTYPE html>
<html lang="ru" ng-app="demo.shef" ng-init="_sessid='<?=bitrix_sessid();?>'">
...
<?require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");?>
Добавим в Ангуляр сервис для общения с сервером и соединим его с контроллерами
* включаем еще одну зависимость
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular-resource.min.js"></script>
* подключаем ngResource
angular.module('demo.shef', [
'ngRoute',
'ngResource',
'ui.bootstrap'
])
* создаем сервис
.service('projectResource', ['$resource', '$rootScope', function($resource, $rootScope){
return $resource(
'/local/modules/shef.def/admin/controller.php?param1=:param1¶m2=:param2&sessid=:sessid',
{sessid: $rootScope._sessid}
);
}])
.controller('ListCtrl', ['$scope', 'projectResource', '$log', function($scope, projectResource, $log) {
}])
.controller('UserCtrl', ['$scope', 'projectResource', '$log', function($scope, projectResource, $log) {
}]);
Теперь мы можем сделать запрос к модулю и получить список пользователей
.controller('ListCtrl', ['$scope', 'projectResource', '$log', function($scope, projectResource, $log) {
$scope.items = {};
var resultGetUsers = projectResource.get({
param1: ['\\Shef\\Def\\Project', '\\Users', 'getUsers'],
param2: []
}, function(){
if(resultGetUsers.response.status == 'success'){
$scope.items = resultGetUsers.values;
$log.debug($scope.items);
}else{
$scope.items = {};
alert(resultGetUsers.response.message);
}
});
}])
Или получить пользователя по ID (берем из URL)
.controller('UserCtrl', ['$scope', '$routeParams', 'projectResource', '$log', function($scope, $routeParams, projectResource, $log) {
$scope.item = {};
$scope.params = $routeParams;
var resultGetUser = projectResource.get({
param1: ['\\Shef\\Def\\Project', '\\Users', 'getUser'],
param2: [$scope.params.id]
}, function(){
if(resultGetUser.response.status == 'success'){
$scope.item = resultGetUser.values;
$log.debug($scope.item);
}else{
$scope.item = {};
alert(resultGetUser.response.message);
}
});
}]);
На несуществующий ID получим alert
Исходный код результата (
https://bel.bitrix24.ru/docs/pub/f6d68...step_3.zip )
Теперь выведем результаты в HTML * для страницы пользователя <dl class="dl-horizontal">
<dt>Имя:</dt>
<dd>{{item.NAME}}</dd>
<dt>Фамилия:</dt>
<dd>{{item.FAMILIA}}</dd>
<dt>Отчество:</dt>
<dd>{{item.OTCHESTVO}}</dd>
</dl>
Видно что {{item.OTCHESTVO}} не определено и не выводится
* для списка пользователей <table class="table table-hover mb_2">
<thead>
<tr>
<th>#</th>
<th>Имя</th>
<th>Фамилия</th>
<th>Логин</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(itemId, item) in items">
<td><a ng-href="#/user/{{itemId}}">{{$index+1}}</a></td>
<td>{{item.NAME}}</td>
<td>{{item.FAMILIA}}</td>
<td>{{item.LOGIN}}</td>
</tr>
</tbody>
</table>
Строки таблицы заполняются перебором (ng-repeat)
Номер формируется через индекс цикла
Ссылка формируется отложено (ng-href)
Ну и фильтр Это самое простое. Настраиваем input на хранение значения фильтра
<input type="text" class="form-control" ng-model="q">
И соединяем его с циклом
<tr ng-repeat="(itemId, item) in items| filter:q">
Итого - вводим значение в фильтре и оно сразу применяется для списка
Итог посмотреть результат можно
тут (
http://onepage.bx-shef.by/article-ang...ar-bitrix/ )
PS : По коду статьи постраничная навигация планировалась. Однако оказалось, что она сильно усложняет понимание. Поэтому в итоге она скрыта.
Назад в раздел