Darragh Kenny
Darragh Kenny

Reputation: 31

Create a preview from user inputed CSS and HTML using angularJS

UPDATE: Solution added below as answer

Im building a snippets manger using angularJS and Ace editor. I have two tabs for CSS and HTML and I want to make a preview tab based on the input of the user, similar to the way http://bootsnipp.com/ works. I have a preview working by injecting the CSS code into a style tag:

<div>
    <style>
        {{snippetsCtrl.snippet.css}}
    </style>
    <div ng-bind-html="snippetsCtrl.snippet.html">

    </div>
</div>

But I know this is a bad idea, and it effects the rest of the app, for example if the user adds

body { display: none; }

the screen goes blank.

I tried using an iframe but I cant figure out how to make the iframe work with angular.

So any suggestions on how to take the code in the $scope and apply it to an iframe??

Upvotes: 1

Views: 2364

Answers (2)

Darragh Kenny
Darragh Kenny

Reputation: 31

Ok, so I managed to figure this one out with with the combination of these previous Questions if anyone is interested:

Is it possible to update angularjs expressions inside of an iframe?

Access AngularJS service from a service inside a different frame

Angularjs: call other scope which in iframe

What I did was create the iframe as a separate Angular application. To send the scope to the iframe app, I used the following code in my main app controller:

snippetsCtrl.updateIframe = function () {
    document.getElementById('iframe').contentWindow.updatehtml(snippetsCtrl.snippet.html);

    document.getElementById('iframe').contentWindow.updatecss(snippetsCtrl.snippet.css);

};

Then in the iframe app.js file I used the following code to add the retrieved data to the scope of this app.

var app = angular.module('iframeApp', ['ngSanitize']);

app.controller('iframeCtrl', function ($scope) {

$scope.html = "<h1>Add Code to see preview here</h1>";
$scope.css = '';

window.updatehtml = function (snippet) {
    $scope.$applyAsync(function () {
        $scope.html = snippet;
    });
};
window.updatecss = function (snippet) {
    $scope.$applyAsync(function () {
        $scope.css = snippet;
    });
};

})

This is basically how I got it to work, its a bit messy but will do for now I think.

One problem I ran into was using $scope.$apply, nothing worked until I updated it to $applyAsync, not sure why.

Upvotes: 0

Ieuan Stanley
Ieuan Stanley

Reputation: 1258

You won't be able to use Angular to modify the contents of the iframe — this is due to the Same-Origin Policy.

The only way I can think of doing it is to create a second page which lies effectively empty to start with which can be dynamically updated (not sure how possible this is with Angular, it's certainly doable with ASP). Create your elements from the data on your page, populate your second page with the details. Then use angular to update the src of your iframe to your new page:

How to set an iframe src attribute from a variable in AngularJS

EDIT: There's a question Here which asks about using angular to create a whole new page. The answer says "do what you want to do another way", but it looks like the question itself includes a way to create a separate page with Angular.

Upvotes: 1

Related Questions