Подтвердить что ты не робот

Escaping &> characters в ng-bind в AngularJs

У меня есть прецедент, где мы можем "&" и ' > ' в строке. например. Джонсон и Джонсон, value > 3. Поэтому, когда ответ от сервера закодирован, следовательно, значение становится "value &ampgt; 3'.

ng-bind не поддерживает следующее:

value > 3 будет отображаться для ngBind, тогда как браузер отображает тот же контент, что и value > 3.

http://jsfiddle.net/HKahG/2/

Ng:bind <div ng-bind="model"></div> 
Ng:bind-html <div ng-bind-html="model"></div>
<div> From Div: value &gt; </div>

Почему это поведение браузера по умолчанию не присутствует в ng-bind?. Я не хочу использовать ng-bind-html (имеет проблемы со значением < и это не html) или ng-bind-unsafe-html.

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

Вопросы:

1) Есть ли другой способ сделать то же самое без использования дополнительной директивы, или это правильный способ обработки закодированных данных?

2) Могу ли я переопределить поведение ng-bind или украсить его по умолчанию?

4b9b3361

Ответ 1

РЕДАКТИРОВАТЬ: пожалуйста, перейдите прямо к нижней части ответа, чтобы получить лучшую версию; ответ в хронологическом порядке; Я получил оптимальный код после нескольких итераций, в конце. Спасибо.

  • Могу ли я переопределить поведение ng-bind или украсить его по умолчанию?

Да. Я сделал очень простую реализацию, которая позволяет ng-bind вести себя так, как вы хотите. Ну... Я не уверен, что это именно то, что вы хотите, но, по крайней мере, оно делает то, что я понял, вы хотите.

Рабочая скрипка: http://jsfiddle.net/93QQM/

И вот код:

module.directive('ngBind', function() {
    return {
        compile: function(tElement, tAttrs) {
            tAttrs.ngBind = 'myBind(' + tAttrs.ngBind + ')';
            return { 
                pre: function(scope) {
                    scope.myBind = function(text) {
                        return angular.element('<div>' + text + '</div>').text();
                    }
                }
            };
        }
    }
});

Это не совсем "дополнительная директива" - это способ "переопределить поведение ng-bind". Он не добавляет новую директиву, он просто расширяет поведение существующей директивы ngBind.

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

Мы делаем функцию доступной через область на этапе предварительной привязки, потому что, если мы это сделаем на фазе постсвязывания, функция будет доступна только после, которую восстановила исходная директива ngBind значение из атрибута (которое будет пустой строкой, потому что функция wil не найдена).

Функция myBind проста и умна: она создает элемент, а текст используется без изменений - как тело элемента, только для немедленного получения через функцию text, которая возвращает содержимое так же, как и "браузер отображает" его.

Таким образом, вы можете использовать ngBind, как обычно, например <div ng-bind="model.content" />, но иметь это измененное поведение.


Улучшенная версия

Вместо прикрепления функции myBind к каждой области применения, где применяется ngBind, на каждой фазе предварительной привязки мы можем привязать ее только один раз к $rootScope, что делает ее сразу доступной для всех областей.

Новая рабочая скрипка: http://jsfiddle.net/EUqP9/

Новый код:

module.directive('ngBind', ['$rootScope', function($rootScope) {
    $rootScope.myBind = function(text) {
        return angular.element('<div>' + text + '</div>').text();
    };
    return {
        compile: function(tElement, tAttrs) {
            tAttrs.ngBind = 'myBind(' + tAttrs.ngBind + ')';
        }
    };
}]);

Гораздо чище, чем предыдущая версия! Конечно, вы можете изменить имя функции myBind на любое другое имя, которое вы хотите. "Стоимость" функции такова: добавьте эту простую функцию в корневую область - вам решать, стоит ли цена.


Еще одна версия

Под влиянием Chemiv ответ... почему бы не удалить функцию из какой-либо области и не сделать ее фильтром? Он также работает.

Еще одна новая рабочая скрипка: http://jsfiddle.net/hQJaZ/

И новый код:

module.filter('decode', function() {
    return function(text) {
        return angular.element('<div>' + text + '</div>').text();
    };
}).directive('ngBind', function() {
    return {
        compile: function(tElement, tAttrs) {
            tAttrs.ngBind += '|decode';
        }
    };
});

Теперь у вас есть три варианта выбора из меню.

Ответ 2

Это HTML:

&gt;

Он может не иметь HTML-тегов, но он все еще HTML. Если вы хотите использовать ng-bind, вашему серверу необходимо вернуть некодированный текст. То есть > вместо &gt;.

Используйте ng-bind-html или измените свой сервер, чтобы вернуть обычный текст без предварительного кодирования html.

Изменить: Быстрая демонстрация, иллюстрирующая использование &gt; и > в JavaScript:

div1.innerHTML = "&gt;";  // write HTML
div2.textContent = ">";   // write plain text
console.log(div1.innerHTML === div2.innerHTML);
console.log(div1.textContent === div2.textContent);

http://jsfiddle.net/XhEcV/

Ответ 3

ng-bind использует метод .text() для замены текста, и, хотя ваш код содержит &gt;, который является разметкой HTML, он неправильно отображается ng-bind. Вы должны использовать ng-bind-html в этом месте, поскольку вы фактически вводите содержимое HTML. В противном случае вы можете заменить > от regex до ' > '.

ex: - model = model.replace(/&gt;/g, '>');

Но в этом случае вам нужно заменить все HTML-разметки, которые не нужны, поскольку ng-bind-html уже работает нормально в вашем случае.

Ответ 4

Да, пусть "украсит" его фильтром:

.filter("decode",function(){
    return function(str){         
      var el = document.createElement("div");
      el.innerHTML = str;
      str =   el.textContent || el.innerText;
      return str;        
    }
});

И используйте его как: <div ng-bind="model|decode"></div>

Рабочий пример: http://jsfiddle.net/HKahG/5/

Вдохновленный этим ответом: fooobar.com/questions/21592/...

Ответ 5

Я помню директиву ngBindHtmlUnsafe, доступную для таких случаев использования.

http://code.angularjs.org/1.0.8/docs/api/ng.directive:ngBindHtmlUnsafe

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

Ответ 6

Почему бы просто не использовать $sce.trustAsHtml?