Inject/embed/$sanitize HTML into AngularJS from JSON data - angularjs

I am faced with an issue that I cannot find a solution for.
So I am trying to create an application that will display tracks taken from soundcloud and display them on my page using the soundcloud embeded player. I will be using DjangoREST to create a JSON list of all the tracks I want displayed. The JSON will have an entry to store the embeded HTML and will be packaged up and sent to the AngularJS front end.
The problem I am facing is that I am unable to actually display the embeded HTML even after using ng-bind-html.
I created a small demo to demonstrate the issue I am facing.
app.js
(function(){
var app = angular.module("tracklist", []);
app.controller("TrackListController", function () {
this.tracks = soundcloudtracks;
});
// Very basic JSON track coming in from DjangoREST
var soundcloudtracks = [
{
title: 'Track1',
artist: 'Artist1',
html: '<iframe width="100%" height="400" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?visual=true&url=https%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F150879755&show_artwork=true&client_id=e72237107739281ffceb867534efd87c"></iframe>',
},
{
title: 'Test2',
artist: 'Artist2',
html: '<iframe width="100%" height="400" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?visual=true&url=https%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F150879755&show_artwork=true&client_id=e72237107739281ffceb867534efd87c"></iframe>',
},
]
})();
index.html
<!DOCTYPE html>
<html ng-app="tracklist">
<head>
</head>
<body>
<div>
<div ng-controller="TrackListController as tracklistcont">
<div ng-repeat="track in tracklistcont.tracks">
<h1>{{ track.title }} - {{ track.artist }} </h1>
<div ng-bind-html="track.html"></div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="app.js"></script>
</body>
</html>
From my understanding I need to $sanitize the incoming HTML but I don't know how to properly sanitize each element within an ng-repeat. Could anyone help me out? I am completely lost at this point.
Thanks for your time.

Ok so I believe I was able to resolve the issue. I just created a method to sanitize my html.
app.js
(function(){
var app = angular.module("tracklist", ['ngSanitize']);
app.controller("TrackListController", ['$scope', '$sce', function($scope, $sce) {
this.tracks = soundcloudtracks;
$scope.deliberatelyTrustDangerousSnippet = function(html) {
return $sce.trustAsHtml(html);
};
}]);
// Very basic JSON track coming in from DjangoREST
var soundcloudtracks = [
{
title: 'Track1',
artist: 'Artist1',
html: '<iframe width="100%" height="400" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?visual=true&url=https%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F150879755&show_artwork=true&client_id=e72237107739281ffceb867534efd87c"></iframe>',
url: 'http://soundcloud.com/forss/flickermood',
},
{
title: 'Test2',
artist: 'Artist2',
html: '<iframe width="100%" height="400" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?visual=true&url=https%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F150879755&show_artwork=true&client_id=e72237107739281ffceb867534efd87c"></iframe>',
url: 'http://soundcloud.com/forss/flickermood',
},
]
})();
index.html
<!DOCTYPE html>
<html ng-app="tracklist">
<head>
</head>
<body>
<div>
<div ng-controller="TrackListController as tracklistcont">
<div ng-repeat="track in tracklistcont.tracks">
<h1>{{ track.title }} - {{ track.artist }} </h1>
<div ng-bind-html="deliberatelyTrustDangerousSnippet(track.html)"></div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="https://code.angularjs.org/1.2.26/angular-sanitize.min.js"></script>
<script src="app.js"></script>
</body>
</html>
Now everything is working as expected!

Related

Embed YouTube video from database in an Angular app

I am embedding YouTube video from database in Angular. If I use it directly without using database then it is working fine. But accessing it from database giving me below error.
Error: [$injector:unpr] http://errors.angularjs.org/1.3.2/$injector/unpr?p0=youtubeEmbedUrlFilterProvider%20%3C-%20youtubeEmbedUrlFilter
I searched on SO and found one question similar to this one.
how to embed video link from database in iframe using angularjs
But while using the same answer I am not able to play YouTube video. Actually video doesn't appear and same error I am getting.
YouTube video from db:
youtubevideo:"https://www.youtube.com/embed/c-z9M6KZs_0"
<div ng-style="{'display':youtubevideo == ''?'none':'block'}">
<iframe title="YouTube video player"
class="YouTube-player" type="text/HTML" width="350" height="194"
ng-src="{{youtubevideo| youtubeEmbedUrl}}" frameborder="0" allowfullscreen></iframe></div>
<!-- Youtube Video Above -->
Below code added in script file.
ProfileApp.filter('youtubeEmbedUrl', function ($sce) {
return function(videoId) {
return $sce.trustAsResourceUrl('https://www.youtube.com/embed/' + videoId);
};
});
What am I doing wrong?
console.clear();
var app = angular.module('myApp', []);
app.config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
'self',
'https://www.youtube.com/**'
]);
});
app.controller('videoController', ['$scope',
function MyCtrl($scope) {
$scope.youtubevideo="https://www.youtube.com/embed/c-z9M6KZs_0";
$scope.getIframeSrc = function(src) {
return src;
};
}
]);
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://code.angularjs.org/1.2.1/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="videoController">
<div class="thumbnail">
<div class="video-container">
<iframe width="100%" ng-src="{{getIframeSrc(youtubevideo)}}" frameborder="0 " allowfullscreen></iframe>
</div>
</div>
</body>
</html>

Show thumbnail for a video url in angular js

I am developing a site in angular js, i am uploading vimeo(https://vimeo.com/) or youtube video url. For this i have to show a thumbnail on my listing so is it possible to show preview of a video url using angular js.
Thank You
You can do this using ng-repeat,
var app = angular.module('myApp', []);
app.config(function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
'self',
'https://www.youtube.com/**'
]);
});
app.controller('videoController', ['$scope',
function MyCtrl($scope) {
$scope.product = [{
name: 'some name',
description: 'some description',
media: [{
src: 'v5Asedlj2cw'
}]
},
{
name: 'some name 2',
description: 'some description 2',
media: [{
src: 'v5Asedlj2cw'
}]
}
]
;
$scope.getIframeSrc = function(src) {
return 'https://www.youtube.com/embed/' + src;
};
}
]);
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://code.angularjs.org/1.5.8/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="videoController">
<div ng-repeat="media in product">
<div class="thumbnail">
<div class="video-container">
<iframe width="100%" ng-src="{{getIframeSrc(media.src)}}" frameborder="0 " allowfullscreen></iframe>
</div>
</div>
</div>
</body>
</html>

how to dynamically add page using ng-include with asp.net MVC using angular js

Here i am trying to call partial view from controller using angular js.
here is my code
<div ng-repeat='t in tabs'>
<div ng-include='t.templateUrl'></div>
<div>
when i try to include like ng-include="'/home/menutemplate'" it will includes the content. How can i dynamically do this? . Help me
t.templateUrl should be valid scope variable and should hold a string(path for the template):
$scope.t.templateUrl = "/home/menutemplate"
And in your template:
<div ng-include="t.templateUrl"></div>
It's exactly like what you did like this example
angular.module("app", []);
angular.module("app").controller("ctrl", function ($scope, $rootScope, $filter) {
$scope.templates = [
{url: "/Application/Partials/home.html"},
{url: "/Application/Partials/page2.html"}
]
});
<!doctype html>
<html ng-app="app" ng-controller="ctrl">
<head>
</head>
<body>
<div class="container">
<div ng-repeat="temp in templates">
<div ng-include="temp.url"></div>
</div>
<script type="text/ng-template" id="/Application/Partials/home.html">
<h1>home.html is here</h1>
</script>
<script type="text/ng-template" id="/Application/Partials/page2.html">
page 2 is here
</script>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js"></script>
</body>
</html>

Passing parameters with space to function

I was writing a code in html5 and angular js. I am encountering a problem in passing parameters with space. Here is my code :
angular.module('MyApp', [])
controller('MyCtrl', function($scope) {
$scope.validate = function(description,code) {
alert(description,code);
}
});
<!DOCTYPE html>
<html>
<body ng-app="MyApp">
<div ng-repeat="x in allItem.items" class="col-75" ng-controller="MyCtrl">
<a href="#" ng-click="validate({{x.itemDesc}},{{x.itemCode}})">
<div class="card item center">{{x.itemName}}
</div></a>
</div>
</body>
</html>
The JSON format is like this
Json contains
allItem
{
items
{
itemName: "egg",
itemDesc: "Egg is very delicious",
itemCode: "EGG"
}
{
itemName: "Tomato",
itemDescr: "Tomato's skin contains vitamins",
itemCode: "TMT"
}
}
I am not able to pass the parameters. I don't know how to pass the text that contains spaces and quotes('). Can anyone help me
Your Json needs to be an array, skip the href="#" and you do not need to bind within ng-click. The code below is fully functioning and running.
angular.module('MyApp', [])
.controller('MyCtrl', function($scope) {
$scope.allItem =
{
items:[
{
itemName: "egg",
itemDesc: "Egg is very delicious",
itemCode: "EGG"
},
{
itemName: "Tomato",
itemDesc: "Tomato's skin contains vitamins",
itemCode: "TMT"
}
]
};
$scope.validate = function(description, code) {
console.log(description,'-', code);
};
});
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-app="MyApp" ng-controller="MyCtrl">
<br/>
<div ng-repeat="x in allItem.items" class="col-75">
<a ng-click="validate(x.itemDesc, x.itemCode)">
<div class="card item center">{{x.itemName}}
</div>
</a>
</div>
</body>
</html>

Angular, data in one controller filter to this data in other

At start i want to say im new in angular. Lets say my page look like this:
index.html:
<body ng-app="application">
<div class="container">
<div class="row">
<div class="col-sm-3 sideBar" ng-controller="NavController">
<input ng-model"search">
</div>
<div class="col-sm-9 content" ng-controller="ContentController">
<div ng-repeat="meet in meets | filter:search">
{{ meet.someData }}
</div>
</div>
</div>
</div>
</body>
And how can i make that input in NavController could filter data from ContentController? I want to do this in two controllers.
I'm not sure why you want to do this in two controllers, but it will be considerably more difficult. The Search functionality acts on the data in the content controller. I am guessing that your layout is driving your controller design.
There are numerous posts here that discuss techniques for this. This one: Share data between AngularJS controllers is well-regarded.
Actually you can just do that in a single controller.
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope) {
$scope.name = [{
"id":1
},{
"id":2
},{
"id":3
}]
});
<!DOCTYPE html>
<html ng-app="angularjs-starter">
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<script src="//code.angularjs.org/1.1.1/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl"><input ng-model='find' />
<div ng-repeat="x in name | filter : find">
{{x.id}}
</div>
</body>
</html>
For understanding, i used numbers as data. :) Hope it helps you
You can have a parent controller over the other two controllers. If you use the controllerAs method you can have controllers inside each other, see Angular Style Guide for helpful information about controllers and controllerAs.
You could write it like that and bind the search model to the ParentController.
Edit: I added another solution that I think is better
var app = angular.module('app', []);
app.controller('ParentController', function() {
this.search = 'p'; //set default just for fun
});
app.controller('NavController', function() {
//nav stuff
});
app.controller('ContentController', function() {
this.meets = [{
data: 'hi'
}, {
data: 'potato'
}, {
data: 'help me'
}, {
data: 'pie'
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app">
<div class="container" ng-controller="ParentController as parentVm">
<div class="row">
<div class="col-sm-3 sideBar" ng-controller="NavController as navVm">
<input ng-model="parentVm.search">
</div>
<div class="col-sm-9 content" ng-controller="ContentController as contentVm">
<div ng-repeat="meet in contentVm.meets | filter:parentVm.search">
{{ meet.data }}
</div>
</div>
</div>
</div>
</body>
I stepped away from this for a bit and thought of another idea that doesn't involve using another controller. Here you are using a factory instead to communicate between the controllers. You have to share an object so that when you change the search.term in the input it will change for every reference.
var app = angular.module('app', []);
app.factory('Searcher', function() {
return {
search: {
term: 'p'
}
};
});
app.controller('NavController', function(Searcher) {
//nav stuff
this.search = Searcher.search;
});
app.controller('ContentController', function(Searcher) {
this.search = Searcher.search;
this.meets = [{
data: 'hi'
}, {
data: 'potato'
}, {
data: 'help me'
}, {
data: 'pie'
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app">
<div class="container">
<div class="row">
<div class="col-sm-3 sideBar" ng-controller="NavController as navVm">
<input ng-model="navVm.search.term">
</div>
<div class="col-sm-9 content" ng-controller="ContentController as contentVm">
<div ng-repeat="meet in contentVm.meets | filter:contentVm.search.term">
{{ meet.data }}
</div>
</div>
</div>
</div>
</body>

Resources