Search code examples
dartdart-polymer

Bind text with line breaks


I have a binding to a string with a line break, like 'Hello\nWorld' in my model. Now I want to display the value in my template using {{x}}. But the line break is not correctly displayed. Does polymer provide any support for outputting <br> for line breaks?


Solution

  • Right now your best option would be to create a Nl2br PolymerElement. The only place you can add mark up is inside of the template, so you'll need a template to split the string and add the <br />s

    Example:

     <nl2br-element text="{{}}"></nl2br-element>
    

    nl2br.dart

    library nl2br;
    
    import "dart:html";
    import 'package:polymer/polymer.dart';
    import "package:polymer_expressions/polymer_expressions.dart";
    
    @CustomTag('nl2br-element')
    class Nl2brElement extends PolymerElement with ObservableMixin {
      @observable String text;
    
      DocumentFragment instanceTemplate(Element template) =>
          template.createInstance(this,
              new PolymerExpressions(globals: {
                'splitnewline': (String input) => input.split("\n")
              }));
    }
    

    nl2br.html

    <polymer-element name="nl2br-element" attributes="text">
      <template>
        <template repeat="{{line in text | splitnewline}}">
          {{line}}<br />
        </template>
      </template>
      <script type="application/dart" src="nl2br.dart"></script>
    </polymer-element>
    

    nl2br_test.html

    <!DOCTYPE html>
    
    <html>
      <head>
        <link rel="import" href="nl2br.html">
        <script src="packages/polymer/boot.js"></script>
      </head>
      <body>
        <template id="nl2br" bind>
          <nl2br-element text="{{}}"></nl2br-element>
        </template>
    
        <script type="application/dart" src="nl2br_test.dart"></script>
      </body>
    </html>
    

    nl2br_test.dart

    library nl2br_test;
    
    import 'dart:html';
    
    main() {
      query("#nl2br").model = "foo\nbar";
    }
    

    You can create a polymer expression that will replace \n with <br />. Right now, polymer sanitizes all html and you can't get around it without DOM manipulation. Since it will make <br /> html safe, foo\nbar will display exactly as foo&lt;br /&gt;bar on the page without showing a line break. Which means this won't do exactly what you want, but if polymer adds a way to display safe html on the page, this would be the way to go.

    library nl2br_mixin;
    
    import "dart:html";
    import "package:polymer_expressions/polymer_expressions.dart";
    
    class Nl2brMixin {
      DocumentFragment instanceTemplate(Element template) =>
        template.createInstance(this,
            new PolymerExpressions(globals: {
              'nl2br': (String input) => input.replaceAll("\n", "<br />")
            }));
    }
    

    You can use this mixin with your PolymerElement

    class CustomElement extends PolymerElement with ObservableMixin, Nl2brMixin {
      @observable
      String text = "foo\nbar";
    }
    

    And use the nl2br expression in your template

    {{text | nl2br}}
    

    Now this probably isn't the best way to get the nl2br expression in your custom element without explicitly putting it in your class. If you have multiple mixins that declare instanceTemplate or declare it in your class, only one of them will work.