AlexZaharow
@AlexZaharow
Программист.

Есть фанаты/любители Angular? Предлагаю обсудить одну находку.?

Здравствуйте.

Update. 2015.10.10 02:31.
Мне кажется, что эта находка очень похожа на xslt-стили для JSON.

Вводная (Находка в конце)

Досталась тут одна задачка. Есть проект и в нём среди прочих компонентов активно используется Angular. Не буду утомлять подробностями проекта. Есть достаточно большой перечень объектов, представленных массивом однотипных данных, например так выглядит один из объектов (ничего особенного):
var arr = [
 {
    position : 66,
    center : [59.7235, 28.4731],
    name : 	"Автомобильная дорога к Карбамидному заводу",
    projectref: "projects/263/?clear_cache=Y",
    pictureprojectref : "images/objects/Карбамидный_завод.300x180.jpg",
    popupText: "текст1 [name] ещё текст [projectref] ещё немного текста [name]. А теперь гляньте сюда: [projectref], классная картинка [pictureprojectref]",
 }
]
:

Обратите внимание на свойство popupText. Это не просто строка - это прообраз результата. Из неё надо получить надпись, которая будет выведена на экран. А в квадратных скобках, соответственно, надо подставить значения полей самого объекта. С одной стороны можно было бы не думать слишком долго и вынести это свойство в какой-нибудь внешний цикл, например:
var arr=[...];
for(var i=0; i<=arr.length-1; i++{
    var arr_i = arr[i];
    arr_i.popupText = "текст1 "+arr_i.name+" ещё текст "+projectref+" ещё немного текста "+name+". А теперь гляньте сюда: "+projectref+", классная картинка "+pictureprojectref+"";
}


Но проблема подкралась откуда не ждали. В другом объекте строка popupText уже другая:

var arr = [
{
    position : 66,
    center : [59.7235, 28.4731],
    name : 	"Автомобильная дорога к Карбамидному заводу",
    projectref: "projects/263/?clear_cache=Y",
    pictureprojectref : "images/objects/Карбамидный_завод.300x180.jpg",
    popupText : "текст1 [name] ещё текст [projectref] ещё немного текста [name]. А теперь гляньте сюда: [projectref], классная картинка [pictureprojectref]",
},
{
    position : 67,
    center : [59.8113, 30.0687],
    name : 	"Концепция транспортного обеспечения территории п. Новоселье, входящего в состав Муниципального образования «Аннинское сельское поселение» Ломоносовского муниципального района Ленинградской области",
    projectref: "projects/226/?clear_cache=Y",
    pictureprojectref : "images/objects/Новоселье.300x142.jpg",
    popupText : "классная картинка [pictureprojectref], находится в описании [projectref]. А название вот такое: [name] ",
}];


И теперь сделать цикл по всем объектам не получится. Законно ли будет применить тут replace? Может да, а может и нет. Во-первых нельзя доверять заменам, чтобы в них не оказалось такой же записи с именем поля (не важно, случайно или по злому умыслу), во-вторых очень хотелось найти что-то поинтереснее. Angular имеет сервис $compile, а это значит, что вместо квадратных скобок, которые я употребил в примерах, можно использовать ангуляровские:

Находка в цикле
bc579e3fe98d47d596d8dbfe057ed96d.png
<!-- сюда будут выводиться popup тексты: -->
<div id="para"></div>


var arr = [
{
    position : 66,
    center : [59.7235, 28.4731],
    name : 	"Автомобильная дорога к Карбамидному заводу",
    projectref: "projects/263/?clear_cache=Y",
    pictureprojectref : "images/objects/Карбамидный_завод.300x180.jpg",
    popupText : "текст1 {{name}} ещё текст <a href=\"{{projectref}}\">{{name}}</a> ещё немного текста {{name}}. А теперь гляньте сюда: {{projectref}}, классная картинка {{pictureprojectref}}",
},
{
    position : 67,
    center : [59.8113, 30.0687],
    name : 	"Концепция транспортного обеспечения территории п. Новоселье, входящего в состав Муниципального образования «Аннинское сельское поселение» Ломоносовского муниципального района Ленинградской области",
    projectref: "projects/226/?clear_cache=Y",
    pictureprojectref : "images/objects/Новоселье.300x142.jpg",
    popupText : "классная картинка {{pictureprojectref}}, находится в описании {{projectref}}. А название вот такое: {{name}} ",
}];

// Вот теперь и один цикл:
for(var i=0; i<=arr.length-1; i++){
    var scope_i = $scope.$new(true);
    var arr_i = arr[i];
    angular.extend(scope_i, arr_i);
    // Находка:
    var temp = $compile(arr_i.popupText)(scope_i);  // angular компилирует строку popupText, подставляя туда данные из объекта
    angular.element("#para").append(temp);  // вывести на экран.
}


В итоге все popupText в желанном виде попадут в #para. Вот такое применение $compile мне и кажется находкой, хотя ситуация со стороны может выглядеть и так:
42a0d57cdc304863b2b9e06901319c9f.png

Может есть ещё варианты как можно иначе сделать эти замены, кроме вышеупомянутых JS replace и angular? (вдруг у вас есть предложить что-то попроще)

P.S. Спасибо, что дочитали :)
  • Вопрос задан
  • 679 просмотров
Пригласить эксперта
Ответы на вопрос 2
@Aves
Так чем же replace хуже-то в итоге?
arr.map(e => e.popupText.replace(/\[(.+?)\]/g, (s, p) => p in e ? e[p] : s))
Ответ написан
@lega
Почему бы и нет, по хорошему сам popup плагин должен этим заниматься.
При этом можно получить профит используя фильтры. А в случае с Angular Light можно использовать асинхронные фильтры (или текстовые директивы) и тогда можно будет что-б шаблон сам доставал текст по ссылкам с сервера, например "{{companyId | loadCompanyNameById}}". Пример на Angular Light, с асинхронным фильтром.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы