Inside a larger legacy app I have a view that uses AngularJS. In this view, I use a directive to display a Bootstrap modal (its content is created on the backend, then appended to the DOM).
No AngularJS methods seem to be working inside the modal. I understand it's because the modal content is appended to the DOM after AngularJS has compiled.
I'm looking for a way to allow the use AngularJS braces and methods inside the modal template. I've tried looking into $compile, $apply, and $digest, but so far I haven't been able to get it to work.
Relevant part of the code:
myApp.directive('formModal', ['$http', function($http) {
return {
restrict: 'E',
scope: true,
replace: true,
template: '...',
link: function postLink(scope){
// ...
$http({url: url}).then(function (response) {
if (response.data.status) {
modal.show({
title: 'Modal title',
content: response.data.form_html,
onShow: function ($modal) {
// ...
}
});
};
})
};
}
};
}]);
And part of the template where the modal is opened:
<form-modal class="btn-success" id="btn-form">
</form-modal>
Related
I want to load different html templates depending on the screen size.
Controller:
$scope.getTemplateUrl = function() {
if ($scope.md) {
return $templateCache.get('library/timelineeditor/slidelibrary/slidelibrary.html')
} else {
return $templateCache.get('library/timelineeditor/slidelibrary/slidelibrary-mobile.html')
}
}
Directive:
function SlideLibrary() {
return {
restrict: 'E',
scope: {},
bindToController: true,
controller: 'SlideLibraryController',
controllerAs: 'vm',
template: '<ng-include src="getTemplateUrl()"/>'
};
}
It loads the right template, but something goes wrong along the way as you can see in the pic:
Are there any best practices around this or do you have any suggestions on how to do it differently?
Currently you are passing template content to src which is trying to make an ajax for fetching that template, that's why you can see 404 error in console. You should just be returning URL form getTemplateUrl method. Because src of ng-include accept templateUrl only, it will take care of loading that template into div.
$scope.getTemplateUrl = function() {
if ($scope.md) {
return 'library/timelineeditor/slidelibrary/slidelibrary.html';
} else {
return 'library/timelineeditor/slidelibrary/slidelibrary-mobile.html';
}
}
I'm pretty new to Angular, so I think template is the wrong word. Here's what I mean:
We have a Rails backend serving up data to an Angular frontend. I need to use an ng-repeat to show off this data. The problem is, the desired template comes as part of the data that Rails serves us. Here's an example:
JSON served by Rails
[
{
data: {
title: "example title",
body: "example body"
},
template: "<h1>{{title}}</h1><p>{{body}}</p>"
},
{
data: {
body: "example body two"
},
template: "<div>{{body}}</div>"
}
]
We don't know how many records there will be, what the templates will look like, or what bindings they call for (body, title, caption, etc). I cannot store the templates locally, so all the data has to come from the Rails backend.
Here is pseudocode of what I'd like to accomplish:
<span ng-repeat="block in blocks">
<template src="block.template" data="block.data"></template>
</span>
This would use the specified template and bind the data object to it.
Again, I'm new to angular so if I need to clarify let me know. Thank you!
EDIT: Here's my attempt at a directive. It doesn't work since it appears that template doesn't have access to the desired template represented by block.template. This wouldn't cover binding the data, so I'd have to work that in once I fixed the directive.
app.directive("template", function() {
return {
template: block.template,
scope: {
block: '=data'
},
restrict: 'E'
};
});
EDIT 2:
Here's another attempt that doesn't work. This one shows the template on screen, but in the console it errors that scope.$watch is not a function
app.directive('template', function ($compile) {
return {
restrict: 'A',
replace: true,
scope: {
tmpl: '=template'
},
link: function postLink(scope, element, attrs) {
scope.$watch('tmpl', function (block) {
element.html(block.template.blank_template);
$compile(element.contents())(block.payload);
});
}
};
});
You can do it with a directive:
basically something along the lines of
//Assuming App is your Angular App Instance and Angular at least 1.4ish
app.directive('template',['$compile', function($c) {
return {
link: function (scope, el, attrs, controller) {
el.html(scope.template);
$c(el.contents())(scope);
},
scope: {
template: "=tpl",
data: "=data"
}
}
});
Then you can use it like so:
<span ng-repeat="block in blocks">
<template tpl="block.template" data="block.data"></template>
</span>
I am developing an angular framework where user can configure header, menu, footer and selected pages using custom directives. To complete this requirement, at one point I need the following. I have seen example on the net, but does not really explain it well.
The requirement is that the templateUrl of the first custom directive shall be replaced with a template attribute that should call another custom directive.
The following code with templateUrl works fine.
angular.module("app",[]);
angular.module("app").controller("productController", ['$scope', function ($scope) {
}]);
angular.module("app").directive("tmHtml", function () {
return {
transclude: false,
scope: {
},
controller: "productController",
templateUrl: "/templates/HideShow.html"
};
});
However, when I change the above code as follows. I am making the change so that my custom directive tmHtml calls another custom directive.
angular.module("app").directive("tmHtml", function () {
return {
transclude: false,
scope: {
},
controller: "productController",
template: ``<hideShow></hideShow>``
};
});
New Directive for hideShow is written as follows
angular.module("app").directive("hideShow", function () {
return {
tempateUrl: "/templates/HideShow.html"
};
});
It's not working. I understand I am missing something here. I could not find out. Appreciate help
Working code:
var app = angular.module('plunker', []);
app.controller('productController', function($scope) {
});
app.directive("hideShow", function() {
return {
templateUrl: "hideshow.html"
};
});
app.directive("tmHtml", function() {
return {
transclude: false,
scope: {},
controller: "productController",
template: "<hide-show></hide-show>"
};
});
the problem is with the spelling of templateUrl in your hideShow directive.
Demo : http://plnkr.co/edit/TaznOeNQ7dM9lyFgqwCL?p=preview
Try define your controller with controllerAs:
angular.module("app").directive("tmHtml", function () {
return {
transclude: false,
scope: {
},
controllerAs: "productController",
templateUrl: "/templates/HideShow.html"
};
});
angular.module("app").directive("tmHtml", function () {
return {
transclude: false,
scope: {
},
controller: "productController",
template: ``<hideShow></hideShow>``
};
});
must be replaced by
angular.module("app").directive("tmHtml", function () {
return {
transclude: false,
scope: {
},
controller: "productController",
template: "<hide-show></hide-show>"
};
});
under the attribute template, you add Html. So, you still have to use snake-case there, like in your Html files
Your first directive may have an eventually scoped attribute that you observe.
Then it may wrap the second directive. If needed, your directives may communicates as parents and children.
I am using a jQuery component in angular with a directive like this:
angular.module('directives.flavr', [])
.directive('flavr', function () {
return {
restrict: 'E',
scope: true,
link: function (scope, element, attrs) {
element.bind('click', function () {
new $.flavr({
title: 'Form',
content: 'HTML form example',
dialog: 'form',
form: {content: '<div ng-include="directives/flavr/templates/loginForm.tpl.html"></div>', method: 'post'},
onSubmit: function ($container, $form) {
alert($form.serialize());
return false;
}
});
});
}
};
});
The flavr popup accept an HTML to build the modal window, is it possible to use a $templateCache html file to store this html ?
If it isn't possible, what is the best way to "pass" som random HTML content to my directive to render whatever I like ?
Ideally, I would like to do something like this:
<flavr html="/* I want to put a templatecache url and be able to load it when the popup is open */"></flavr>
Any ideas ?
I'm new to AngularJS and I feel like I'm just scratching the surface of what's possible with the framework. However, I'm running into problems with the sce.trustAsHtml function. I'm running AngularJS 1.2.4.
In my application, I'm loading items using JSON. These items are displayed in a list using a directive. Sometimes, I would want to inject HTML into the retrieved content (e.g. to make links clickable).
I've read I can use $sce.trustAsHtml to allow html in the binds. However, the following snippet isn't working. I would expect all items to be replaced with a bold text 'test', but instead it's displaying <strong>Test</strong> for each item.
Is there a simple way to make this snippet work?
angular.directive('ngStream', function($timeout, $sce) {
var url = "getitems.json";
return {
restrict: 'A',
scope: {},
templateUrl: 'templates/app_item.html',
controller: ['$scope', '$http', function($scope, $http) {
$scope.getItems = function() {
$http.get(url,{}).success(function(data, status, headers, config) {
$scope.items = data;
});
}
}],
link: function(scope, iElement, iAttrs, ctrl) {
scope.getItems();
scope.$watch('items', function(newVal) { if (newVal) {
angular.forEach(newVal, function(vars,i) {
# Example html string for testing purposes.
var editedContent = '<strong>Test</strong>';
newVal[i].contentHtml = $sce.trustAsHtml(editedContent)
});
}});
},
}
});
What's on your template? $sce.trustAsHtml must be used with ng-bind-html instead of normal ng-bind (or {{}})