-1

I laying out a styleguide with code examples within an AngularJS app.

In the past, I've used <pre>. This no longer seems to work. I've tried it in codepen, and it still parses the HTML.

I do not want this.

<h1>I DO want this.</h1>

I'm guessing there's a filter to encode or decode the HTML, but I don't know which way I need to go. My intuition tells me I need to encode. However, everytime I try to google search a solution I get the opposite answers of what I want.

So for anyone who's better at googling than I am or know how to do this, please help.

Edit To appease the would be SO demigods, where's the code I ended up with...

This is how I started:

<xmp><button>Some example Button</button></xmp>

<xmp> is deprecated, and has line break/whitespace issues. Couldn't use it.

Next one...

<pre><button>Some example Button</button></pre>

This sucked too, because it still parses the child nodes, meaning would get a button instead of a string.

What I ended up with:

// Template

    <div class="sgForms__ex">
        <div ng-bind-html="sgTrustHtml(buttons)"></div>
    </div>
    <div class="sgForms__code">
        <div ng-bind="buttons"></div>
    </div>

// Controller

angular.module('StyleGuide')
  .controller('StyleGuideFormsController', ['$scope', '$sce', 'ListHelper',
  function ($scope, $sce, listHelper) {

    $scope.sgTrustHtml = function (i) {
        return $sce.trustAsHtml(i);
    };

    $scope.buttons = '<button type="button" class="btn btn-primary">Call to Action</button>' +
        '<button type="button" class="btn btn-default">Secondary CTA</button>'+
        '<button type="button" class="btn btn-default">Inactive</button>';


}]);

I'm still running into an issue with line breaks. Note sure how I'm going to work around that.

Plummer
  • 6,522
  • 13
  • 47
  • 75
  • did you tried `ng-bind-html` directive? – Pankaj Parkar Feb 12 '16 at 19:21
  • @PankajParkar so store the HTML to a $scope and then pop it in? http://stackoverflow.com/a/14514299/1202630 – Plummer Feb 12 '16 at 19:28
  • You have to show your code, where's there a scope value being set? Text is typically HTML-escaped by default, so it's hard to tell what you're doing. – Ruan Mendes Feb 12 '16 at 19:46
  • `
    ` never behaved the way you describe. `` does.
    – Daniel Beck Feb 12 '16 at 19:50
  • @DanielBeck `` is deprecated. There's also line breaking and whitespace issues. with it. – Plummer Feb 12 '16 at 19:53
  • Hm, I honestly hadn't realized it was deprecated (not something I've needed to use, much). OK, I got nothin, sorry. – Daniel Beck Feb 12 '16 at 19:55
  • I think this gets be where I want. https://docs.angularjs.org/api/ngSanitize/service/$sanitize I was hoping to avoid putting the code example content into the controller, but oh well. – Plummer Feb 12 '16 at 19:58
  • Wait a minute, doesn't ng-bind do what you want by default? http://jsfiddle.net/8eyq7rs7/ `$sanitize` is for when you want to parse html in data (`ng-bind-html`), but if you just ng-bind or {{}} it it'll come out unparsed... – Daniel Beck Feb 12 '16 at 20:06
  • Yeah, apparently. Like I said, in my searching, the only answers I came up with were for the opposite of what I wanted to do. `ng-bind` was what I wanted. BUT, what I also need are some line breaks in the code exampes, which I don't know how to pass through the being without it spitting out the line-break with the rest of the contents. – Plummer Feb 12 '16 at 20:11
  • @Plummer Show your code already! As I've said, from your explanation, it should be working. If I set `$scope.some = "

    Hello

    "`, you will see angled brackets on the screen
    – Ruan Mendes Feb 12 '16 at 20:16
  • So... we're back to `
    `? http://jsfiddle.net/8eyq7rs7/2/   Gotta admit at this point I'm pretty confused about what it is you're asking.
    – Daniel Beck Feb 12 '16 at 20:17

2 Answers2

2

The only problem with the code you've shown is that you are using buttons but the scope only has examples. The following snippet shows the HTML parsed, and unparsed.

To display newlines where you are displaying the code, just wrap it with a pre (or use CSS white-space: pre)

var myApp = angular.module('myApp', [])
  .directive('myDirective', ['$sce',function($sce) {}])
  .controller('StyleGuideFormsController', ['$scope', '$sce',
    function($scope, $sce) {
      $scope.sgTrustHtml = function(htmlString) {
        return $sce.trustAsHtml(htmlString);
      };

      $scope.examples = '<button type="button" class="btn btn-primary">Call to Action</button>\n' +
        '<button type="button" class="btn btn-default">Secondary CTA</button>\n' +
        '<button type="button" class="btn btn-default">Inactive</button>';
    }
  ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">

  <div ng-controller="StyleGuideFormsController">
    <pre><div ng-bind="examples"></div><pre>
    <div ng-bind-html="sgTrustHtml(examples)"></div>
  </div>

</div>
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • @DanielBeck Fixed it – Ruan Mendes Feb 12 '16 at 20:52
  • the `examples` bit was a typo from carrying over to the answer. In my code, using `ng-bind` works, but I don't know how to persist lines breaks. – Plummer Feb 12 '16 at 21:36
  • @Plummer The focus of your question was displaying the code instead of interpreting the code. If you put a pre around the HTML that displays your code, then newlines will be treated as new lines instead of collapsed into whitespace like HTML usually does. – Ruan Mendes Feb 13 '16 at 15:17
-1

You can use a function strip_tags to clean up your code.

angular.module('filters', []).factory('truncate', function () {
    return function strip_tags(input, allowed) {
      allowed = (((allowed || '') + '')
        .toLowerCase()
        .match(/<[a-z][a-z0-9]*>/g) || [])
        .join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
      var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
        commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
      return input.replace(commentsAndPhpTags, '')
        .replace(tags, function($0, $1) {
          return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
        });
    }
});

Controller:

angular.module('myApp', ['filters'])
.controller('IndexController', ['$scope', 'truncate', function($scope, truncate){

  $('#myDivPre').replaceWith((truncate($('#myDiv'), '<a><br>')));

}]);

HTML:

<div id="myDivPre"></div>
Jean Marcos
  • 1,167
  • 1
  • 12
  • 17
  • 1
    Isn't this the opposite of what the OP wants, they don't want to strip, they want to maintain the tags. – Ruan Mendes Feb 12 '16 at 19:43
  • @JuanMendes: And I love the downvotes fairies paying me a visit because they don't understand the question. – Plummer Feb 12 '16 at 19:48
  • @Plummer One of the downvotes was mine (for the question, not this answer since Jean just misunderstood the question), I kind of understood it. However, in my book, a question without code is always worth a downvote, you did not explain well what you are currently doing. – Ruan Mendes Feb 12 '16 at 19:49
  • @JuanMendes my bad, dude. I was using `
    ` which doesn't work.  The example I gave are essentially what SO does already, which is what I posted.  If you inspect SO, they use `
    `, but I'm sure they have some JS driving it.
    – Plummer Feb 12 '16 at 19:55