Directive render from template - javascript

I am new to angularjs. I am trying to make an custom element directive loaded from a model. If I use this directive in the HTML file works, but what I want to do is use this directive in a model. It is possible to trigger the directive after define the model ?
JS:
window.app = angular.module('myapp', ['ngSanitize']);
app.directive("myWidget", function() {
return {
restrict: 'E',
template: "<p>Hello World</p>",
};
});
app.controller('page', ['$scope', '$sce', function($scope, $sce) {
$scope.myhtml = $sce.trustAsHtml("<my-widget></my-widget>")
}]);
HTML:
<div ng-app="myapp">
<div ng-controller="page">
<my-widget></my-widget>
<div ng-bind-html="myhtml"></div>
</div>
</div>

Related

Angular directives, only one works per page

I have little problem with my angularJS directive, i want to display 2 photos in different way by using other html codes, but here comes a problem, that only one directive can works per page, the second one works only when i comment the previous one, there are no any errors in the browser console so i totally losing my mind trying to figure how to fix this problem.
ps displayed photos are taken form json file.
Angular:
(function(angular) {
'use strict';
angular.module('SinglePost', ['ngSanitize', 'ui.bootstrap'])
.controller('Controller', ['$scope', '$http', '$sce', '$location', function($scope, $http, $sce, $location) {
var weburl = document.URL;
var postId = weburl.substr(-2, 2)
$http.get(link + 'json=get_post&post_id=' + postId).then(function(response, date, content) {
$scope.content = response.data.post;
$scope.CategoryID = response.data.post.categories[0].id;
IDcategory = $scope.CategoryID
console.log(IDcategory)
$sce.trustAsHtml(content);
});
}])
.directive('myPost', function() {
return {
restrict: 'AEC',
scope: {
myPost: '='
},
templateUrl: '../common/directive/single-post.html'
};
});
})(window.angular);
(function(angular) {
'use strict';
angular.module('SinglePostsCategory', ['ngSanitize', 'ui.bootstrap'])
.controller('Controller', ['$scope', '$http', '$sce', '$location', function($scope, $http, $sce, $location) {
$http.get(link + 'json=get_category_posts&id=1').then(function(response, date, contents) {
$scope.myList = {
items: [
$scope.content = response.data.posts[0],
$scope.content = response.data.posts[0]
]
}
});
}])
.directive('myPost', function() {
return {
restrict: 'A',
scope: {
myPost: '='
},
templateUrl: '../common/directive/single-subpost_category.html'
};
});
})(window.angular);
HTML:
<div class="col-md-12">
<div ng-app="SinglePost">
<div ng-controller="Controller">
<div my-post="content">
<h1>CONTENT</h1></div>
</div>
</div>
<div class="row">
<div ng-app="SinglePostsCategory">
<div ng-controller="Controller">
<div ng-repeat="content in myList.items">
<div my-post="content">
<h1>CONTENT</h1></div>
</div>
</div>
</div>
</div>
</div>
any suggestion how to fix it? :)
function(angular) {
'use strict';
angular.module('SinglePost', ['ngSanitize', 'ui.bootstrap'])
.controller('SingleController', ['$scope', '$http', '$sce', '$location', function($scope, $http, $sce, $location) {
var weburl = document.URL;
var postId = weburl.substr(-2, 2)
$http.get(link + 'json=get_post&post_id=' + postId).then(function(response, date, content) {
$scope.content = response.data.post;
$scope.CategoryID = response.data.post.categories[0].id;
IDcategory = $scope.CategoryID
console.log(IDcategory)
$sce.trustAsHtml(content);
});
}])
.directive('mySinglePost', function() {
return {
restrict: 'AEC',
scope: {
myPost: '='
},
templateUrl: '../common/directive/single-post.html'
};
});})(window.angular);
angular.module('SinglePostsCategory', ['ngSanitize','ui.bootstrap'])
.controller('SinglePostsController', ['$scope', '$http', '$sce', '$location', function($scope, $http, $sce, $location) {
$http.get(link + 'json=get_category_posts&id=1').then(function(response, date, contents) {
$scope.myList = {
items: [
$scope.content = response.data.posts[0],
$scope.content = response.data.posts[0]
]
}
});
}])
.directive('mySinglePostsCategory', function() {
return {
restrict: 'AEC',
scope: {
myPost: '='
},
templateUrl:'../common/directive/singlesubpost_category.html'
};
});})(window.angular);
Rename your directive or your Controller name, Sometimes within the same page with two modules with the same controller name could cause the problem. I recommend to change both Controller names to be distinguishable.
For what I have seen I dont know why you need two module within one page . Can you combine it into one module and use two controllers?
HTML:
<div class="col-md-12">
<div ng-app="SinglePost">
<div ng-controller="SinglePostController">
<div my-single-post="content">
<h1>CONTENT</h1></div>
</div>
</div>
<div class="row">
<div ng-app="SinglePostsCategory">
<div ng-controller="SinglePostsController">
<div ng-repeat="content in myList.items">
<div my-single-posts-category="content">
<h1>CONTENT</h1></div>
</div>
</div>
</div>
</div>
You can not create same name directives even in the different module.
the module is used to divide the develop module,but it can't avoid polluting the namespace.if you want to use the module B in module A,you just need to inject module B like
angular.module('SinglePost', ['ngSanitize', 'ui.bootstrap','SinglePostsCategory'])
but make sure the directive and controller's name is different

AngularJS display json by directive

I have little problem with AngularJS, I wanted to make directive to display json imported from other website, directive working, but it doesnt show anything from angular binds(when i was using this code by just putting it hardway, everything was working).
HTML
<div ng-app="docsIsolateScopeDirective">
<div ng-controller="Controller">
<my-post info="post"></my-post>
</div>
</div>
ANGULAR
(function(angular) {
'use strict';
angular.module('docsIsolateScopeDirective', ['ngSanitize', 'ui.bootstrap'])
.controller('Controller', ['$scope','$http','$sce', function($scope, $http, $sce) {
$http.get(link+'json=get_recent_posts&callback=&count=1').then(function(response, date, contents){
$scope.contents = response.data.posts;
$sce.trustAsHtml(contents);
});
}])
.directive('myPost', function() {
return {
restrict: 'E',
scope: {
customerInfo: '=info'
},
templateUrl: 'single-post.html'
};
});
})(window.angular);
SINGLE-POST.HTML
<article>
<div class="news-container">
<span class="news-category">{{content.categories[0].title}}</span>
<h1 class="news-title">{{content.title}}</h1>
<span class="news-date">{{content.date}}</span>
<div class="news-image">
<img src="{{content.thumbnail_images.full.url}}" />
</div>
<!-- .news-image -->
<div class="news-entry">
<p ng-bind-html="content.content">{{content.content}}</p>
</div>
</div>
Any ideas? :)
You save your response as
$scope.contents = response.data.posts;
And you pass into directive variable post . Maybe you should pass contents ?
And also in your directive you have customerInfo not content.
its always better to use jsonp for calls to outer domains.
Can you try doing this?
$http.jsonp('some/trusted/url', {jsonpCallbackParam: 'callback'})
Whitelisting urls is also apt.
Pass $scope.contents to info.
$scope.contents = response.data.posts;
<div ng-app="docsIsolateScopeDirective">
<div ng-controller="Controller">
<my-post info="contents"></my-post>
</div>
</div>
You need to use customerInfo in the template single-post.html and also pass contents scope object to your directive
Additionally, Using trustAsHtml() method correctly.
$scope.contents = $sce.trustAsHtml(response.data.posts);
Here is a simplified example:
(function(angular) {
'use strict';
angular.module('docsIsolateScopeDirective', [])
.controller('Controller', ['$scope',
function($scope) {
$scope.contents = {
title: "test"
};
}
])
.directive('myPost', function() {
return {
restrict: 'E',
scope: {
customerInfo: '=info'
},
template: '<article>\
<h1 class="news-title">{{customerInfo.title}}</h1>\
</article>'
};
});
})(window.angular);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="docsIsolateScopeDirective">
<div ng-controller="Controller">
<my-post info="contents"></my-post>
</div>
</div>

Angularjs: Callback to parent controller

Please consider the following code: it has a directive myItem with isolate scope. Each item will display a button that will call delete() on the directive controller. I'd like this to trigger a refresh in the outer controller (AppController). But of course the refresh() function can not be found, because of the isolated scope.
<html>
<body ng-app="question">
<div ng-cloak ng-controller="AppController">
<my-item ng-repeat="item in list" data="list">
</my-item>
<input type="text" maxlength="50" ng-model="new_item" />
<button ng-click="add(new_item)">+</button>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script>
(function () {
var app;
app = angular.module('question', []);
app.controller('AppController', [
'$scope', '$http', function ($scope, $http) {
$scope.list = [];
function refresh(){
$http.get('/api/items').then(
function(response){
$scope.list = response.data;
}
);
}
$scope.add = function(item){
$http.post('/api/items', { item: item }).then(refresh);
};
refresh();
}
]);
app.directive('myItem', function() {
return {
scope: {
item: '=data',
},
// directive template with delete button
template: '{{ item }} <button ng-click="delete(item)">-</button>',
restrict: 'E',
// directive controller with delete function
controller: [ '$scope', '$http', function($scope, $http) {
$scope.delete = function (card) {
// This is where it goes wrong! refresh does not exist
$http.delete('/api/items' + card.id).then(refresh);
}
}]
};
});
})();
</script>
</body>
</html>
One thing I could do is add ng-change to the myItem directive, but that would involve requiring ngModelController which seems overkill.
Other things I can think of:
Add something like onchange: '#' to the scope attribute of the directive, then set onchange = refresh in the html. Call the onchange expression instead of refresh inside the delete function. But this feels like I'm re-implementing ng-change?
Add require: '^AppController' to the directive. Then I guess I could call refresh on the parent controller directly. That seems like it violates loose coupling.
Don't use isolate scope at all. That would mean we inherit from the parent scope and refresh is available. But then my directive implicitly assumes that the scope will hold an item. Which also violates loose coupling, but in an implicit way.
So my question is: which is the correct way to let the parent controller know it should refresh its contents?
IMO, the first way would be the best way. The directive receives a function callback from outside which is executed by the directive when necessary. Like this the two directives are loosely coupled. It's similar to ng-change which is an attribute that is used by ng-model directive.
Example: Directive
app.directive('myItem', function() {
return {
restrict: 'E',
scope: {
item: '=data',
myItemDeleteCallback: '&myItemDeleteCallback'
},
template: '{{ item }} <button ng-click="delete(item)">-</button>',
controller: [ '$scope', '$http', function($scope, $http) {
$scope.delete = function (card) {
// This is where it goes wrong! refresh does not exist
$http.delete('/api/items' + card.id).then(function () {
$scope.myItemDeleteCallback();
});
}
}]
};
});
Usage: Controller
app.controller('AppController', ['$scope', '$http', function ($scope, $http) {
$scope.list = [];
$scope.refresh = function (){
$http.get('/api/items').then(
function(response){
$scope.list = response.data;
}
);
};
$scope.add = function(item){
$http.post('/api/items', { item: item })
.then($scope.refresh);
};
refresh();
}]);
Usage: Template
<div ng-cloak ng-controller="AppController">
<my-item my-item-delete-callback="refresh()" ng-repeat="item in list" data="list">
</my-item>
<input type="text" maxlength="50" ng-model="new_item" />
<button ng-click="add(new_item)">+</button>
</div>

ngBindHtml not Rendering Sanitized HTML

I've got a simple angular app, and I'm trying to inject some html into the page using ngBindHtml. However, it's not being injected. Here's my HTML:
<main id="main" ng-bind-html="oreGen | trust"></main>
And here's my angular app:
angular.module('programApp', ['programApp.controllers','programApp.filters','ngSanitize']);
angular.module('programApp.controllers', [])
.controller('programController', ['$scope', '$filter', function($scope, $filter){
$scope.oreGen = '<div class="oreFunction" ng-click="collectFunction(\'parenthesis\', 1)">test text</div>';
$scope.collectFunction = function(value1, value2){
alert(value1 + value2);
};
}]);
angular.module('programApp.filters', []).filter('trust', ['$sce', function($sce){
return function(text) {
return $sce.trustAsHtml(text);
};
}]);
When the page is loaded, nothing appears inside the main element.
Here's a codepen: http://codepen.io/trueScript/pen/MwbVpO?editors=101
You can see the div being ngBinded does not appear. Why is this?
You can use a directive instead a filter. Please look at this JSFiddle
HTML:
<div ng-app="myApp" ng-controller="programController">
<dir id="main" content="oreGen"></dir>
</div>
JS:
angular.module('myApp', [])
.controller('programController', ['$scope', '$filter', function ($scope, $filter) {
$scope.oreGen = '<dir class="oreFunction" ng-click="collectFunction(\'parenthesis\', 1)">test text</dir>';
$scope.collectFunction = function (value1, value2) {
alert(value1 + value2);
};
}])
.directive('dir', function ($compile, $parse) {
return {
restrict: 'E',
link: function (scope, element, attr) {
scope.$watch(attr.content, function () {
element.html($parse(attr.content)(scope));
$compile(element.contents())(scope);
}, true);
}
}
});

Angular directive not working in ionic.js

I have some troubles to get my directive to load in my ionic.js web app using angular.
I can pass the variable {{someTitle}} from the controller to the template, however the directive does not get loaded, i.e. <div class="blaha" ng-transclude>abc123</div> does not get passed to the template... Am I missing something fatal below:
Ionic template:
<ion-view title="Roll the Dice">
<ion-content has-tabs="true">
<div my-dice>{{someTitle}}</div>
<div class="card">
<div class="item item-text-wrap">
{{someTitle}}
</div>
</div>
<button class="button button-dark button-full button-positive">
Full Width Block Button
</button>
</ion-content>
</ion-view>
Controller code:
'use strict';
angular.module('TrueDice.controllers', [])
// A simple controller that fetches a list of data from a service
.controller('HistoryIndexCtrl', function($scope, TrueRandomService) {
if($scope.rands="undefined"){
$scope.rands = [];
}
TrueRandomService.getRand(1).success(function(data){
$scope.rands.unshift(data);
console.log(data);
});
})
.controller('HistoryDetailCtrl', function($scope, $stateParams, TrueRandomService) {
//currently empty
}).controller('RollViewCtrl', function($scope){
$scope.someTitle="BLA";
}).directive('my-dice', ['$rootScope', function($rootScope) {
return {
restrict: 'E',
template: '<div class="blaha" ng-transclude>abc123</div>',
replace: true,
transclude: true,
scope: {},
controller: function($scope, $element) {
//currently empty
}
}
}]);
Remove - from directive name:
directive('myDice', ['$rootScope', function($rootScope) {
and according to restrict: 'E', you should place element in html:
<my-dice>{{someTitle}}</my-dice>
example

Categories