Создание пользовательской привязки для nl2br в Knockout.js

Я пытаюсь написать пользовательскую привязку для замены «/n» на «<br />» в элементе «<p>».

Я понимаю концепцию более или менее, но я изо всех сил пытаюсь заставить ее работать. Может ли кто-нибудь предложить, где я ошибаюсь. Я действительно не хочу использовать вычисляемую наблюдаемую, так как хочу сохранить реальное значение, используя «/n», а не «<br />».

ko.bindingHandlers.nl2br = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var field = valueAccessor();
        field.replace(/\n/g, '<br />');
        $(element).val(field)
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var field = valueAccessor();
        field.replace(/\n/g, '<br />');
        $(element).val(field)
    }
};

person Wellso    schedule 08.08.2013    source источник
comment
Для тех, кому просто нужно визуально получить новые строки, где в тексте есть символ \n: это возможно с одним css-свойством - см. следующий вопрос: stackoverflow. ком/вопросы/17422895/   -  person David Rettenbacher    schedule 16.10.2015


Ответы (1)


TL;DR Ответ

ko.bindingHandlers.nl2br = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var field = ko.utils.unwrapObservable(valueAccessor());
        field = field.replace(/\n/g, '<br />');
        ko.bindingHandlers.html.update(element, function() { return field; });
    }
};

Полный ответ

Во-первых, вызов replace, вероятно, должен быть:

field = field.replace(/\n/g, '<br />');

В противном случае новая строка отбрасывается.

Кроме того, я бы не рекомендовал устанавливать такое значение элемента напрямую. Положитесь на существующие обработчики (которые предположительно хорошо протестированы в различных браузерах), чтобы выполнить тяжелую работу. См. R.P. Сообщение в блоге Нимейера на эту тему (в частности, пункт 3).

Вы можете использовать либо привязку text, которая будет буквально отображать "<br />" или (если вы доверяете входным данным!) привязка html, если вы хотите визуализировать новую строку для <br />. Последний выглядит так:

ko.bindingHandlers.nl2br = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var field = ko.utils.unwrapObservable(valueAccessor());
        field = field.replace(/\n/g, '<br />');
        ko.bindingHandlers.html.update(element, function() { return field; });
    }
};

ko.applyBindings({ description: ko.observable("This is\nSparta!") });
p, pre { background-color: #dde; margin: 4px 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<strong>Text version in &lt;p&gt;:</strong>
<p data-bind="text: description"></p>
<hr />
<strong>Text version &lt;pre&gt;:</strong>
<pre data-bind="text: description"></pre>
<hr />
<strong>NL2BR version in &lt;p&gt;:</strong>
<p data-bind="nl2br: description"></p>

person Jeroen    schedule 08.08.2013
comment
Забыл упомянуть, что мое значение было наблюдаемым, и его нужно было вызывать как функцию, чтобы вернуть значение. Спасибо за помощь! - person Wellso; 08.08.2013
comment
@Wellso В этом случае лучше использовать unwrapObservable, см. этот совет. Мой ответ отсутствовал в этом отношении, я обновил его соответственно. - person Jeroen; 01.07.2015