I have created a directive in angularJS as <print-note print-data='printData' id='notePrintDiv'></print-note> this directive will take some object and create a formatted html for printing, but I don't want to show the formatted html in my main html I want the formatted html for printout. so I was hopping if there is any way in angularJS where in I just create the element and pass the scope object to it like angular.element("<print-note print-data='printData' id='notePrintDiv'></print-note>"); or any other way and get its innerHTML.
P.S. I can also achieve the same with making outer html of directive template as display: none but that seems to be a bit hacky way.
The $compile service should be able to do this. Inject it in your controller where you have access to the scope (with printData).
var element = $compile('<print-note print-data="printData" id="notePrintDiv"></print-note>')($scope);
I had to achieve samething in a AngularJS app - I kept the directive for Print-Button and I kept id for the div or HTML block that was targeted to be printed and kept that div/html ng-show=false. I think it's one of the right way to get the required task done.
Related
i am not able to access Model for model in below plunkr, please find plunkr below.please help.
<div ng-controller="PersonCtrl">
<h2>Teens - using external HTML file as template</h2>
<iframe src="teen-external.html"></iframe>
</div>
Here's the Plunkr for any ref.
You have a couple of problems in your example, first the html source was loaded in iframe, which loads it as a simple html and renders it inside the iframe without angular parsing it to do all the mastache interpolation.
To correct this since you've already created a directive that renders the teen-external.html which would allow angular to parse the said html and interpolate the relevant fields. to do this simply use the directive inside your index.html file like.
<teen-internal> </teen-internal>
or
<div teen-internal></div>
Another problem is that you're trying to access a variable/model defined inside the parents $scope which is not possible without going via the $scope.$parent. Even if you do it using the $parent it is considered a really bad practice. To this a bit more elegantly angular provides a sort of model/variable passing from parent to the child, to do this you need to change both the index.html and the teensInternal directive code.
in your index.html
or
<div teens-internal teens="teens"></div>
This sets the teens property on the teensInternal's $scope to the teens from the parent's(PersonCtrl) $scope. Now in your directive code you must define how the binding works for teens property, here you can define it as a read only # also called one way binding (modification done inside teensInternal is not reflected inside the parent controller) or as writable = two way binding (both teensInternal and PersonCtrl share the same object, so the modifications are reflected in both sides) to do this change
scope: {
},
to
scope: {
teens: '=' // or "#" for one way binding
},
This tells the directive that whatever was passed to <teens-internal teens="teens"></teens-internal> through teens="<model's name>" can be used inside the directive's $scope.
Plunkr: plunkr source
Introduction
For the project I am working on, I am trying to tackle a particular problem in the 'angular way', however I think I must be missing something because no matter what I try I continue to reach brick wall.
The crux of this issue is I am dynamically loading data from a backend that describes different components that are visible to the user. That's not the issue itself, but rather the issue of the particular & proper 'angular' way to turn a list of 'models' describing the components into actually rendered HTML.
Problem
What I am trying to create is basically the following:
Start off with a parent directive that uses ng-repeat for a scoped list called "models", which contains zero or more "components":
<parent-directive ng-repeat="model in models" model="model"></parent-directive>
The ng-repeat directive creates N copies of that original directive with different 'model' arguments (for each object in the $scope.models array).
// this is just for demonstrative purposes, it obviously looks different in source
<parent-directive model="child1"></parent-directive>
<parent-directive model="child2"></parent-directive>
<parent-directive model="child3"></parent-directive>
issue! => The parentdirective gets transformed into a specific child directive depending on data (in this case, called 'type') contained within the javascript object:
<parent-directive model="..."></parent-directive>
turns into
<child-directive-one model="..."></child-directive-one>
or
<child-directive-two model="..."></child-directive-two>
dependent on what the value 'model.type' is.
The child directive then renders into it's own custom HTML (outside the scope of this problem) using data passed to it. If we continued the example from above, that HTML should render into the following (hopefully):
<child-directive-one model="child1"></child-directive-one>
<child-directive-one model="child2"></child-directive-one>
<child-directive-two model="child3"></child-directive-two>'
Followed by (and this is outside the scope of the issue but just to see it through to the end) each directive rendering into its own HTML:
<div>in childDirectiveOne, text is: This is text contained inside child1</div>
<div>in childDirectiveOne, text is: This is text contained inside child2</div>
<div>in childDirectiveTwo, text is: This is text contained inside child3</div>
Source
I've been trying lots of different variations of things to try and get it to work (involving the link function, using $compile, etc), but this source is provided with all of those attempts stripped out. Here's the source I've developed so far:
removed source (was filled with errors). Solution that Scott helped me out with is below:
Conclusion
Thanks for any advice in advance.
Update:
Solution exists here (thanks again to Scott).
I'm not sure exactly why you can't just have a single directive, however something like the following might work. Instead of repeating the parent directive you just pass in the models and have that directive repeat and create each of the child directives.
<parent-directive the-models="models"></parent-directive>
Parent directive template:
<div ng-repeat="model in models"....>
<child-directive ng-if="YOUR CONDITION"></child-directive>
<child-directive2 ng-if="YOUR CONDITION"></child-directive>
</div>
I need to append a directive's template AFTER an input field. The original input field needs to remain - I can't just create a duplicate of it. My thought for this was to, in the controller, use jQuery to add a DIV after the input field, and add an attribute for the directive to the div. However, in practice, that doesn't work - the div is created and added, but the directive doesn't activate.
The problem, I know, is that the jQuery-added div is not yet recognized by the angularjs controller - it appears AFTER angularjs runs over the controlled html.
I know that part of the problem is that you're not supposed to use jQuery in the controller, but I honestly can't think of another way to do it. Is there some way to cause the angularjs controller to look at this new div?
The original HTML looks like the following.
<input name="generatedString_1234567890">
I run jquery over the page to add a controller to the body. The relevant code looks similar to this:
jQuery('body').attr('ng-controller','MainCtrl');
angular.module('app',['DataTools']);
angular.element(document).ready(function(){
angular.bootstrap(document, ['app']);
});
Inside the angularjs, I run a resource to get a json string containing the relevant changes to the DOM, in terms of attributes that need to get added to the inputs and certain understood flags that require specific coding. The relevant task I'm trying to accomplish looks like this, where $(this) is the input field for the DOM.
jQuery(document).find('input.FormField,select.FormField').each(function(){
// Inside a case statement based on certain flags
var d = $('<div/>');
d.attr("ng-model", 'adors.'+label);
// Relevant code that adds attributes to the div - including the required directives
$(this).hide().after(d);
}
I am trying to create code that looks more like this (VERY GENERIC):
<input name="generatedString_1234567890" ng-hide="true" ng-model="input.uniqueKey">
<div special-input="time" ng-model="input.uniqueKey">
<select ng-repeat="hour in hours">
<select ng-repeat="minute in minutes">
</div>
I'm using AngularJS to design a small app for searching. I have a div that's currently empty, and after running a function, for it to replace it with a div that has ng-include. The div replaces just fine, but ng-include doesn't load up.
I'm currently running the following in console for testing to see get it running. How would I go about getting this to work? Any help is appreciated!
document.getElementById("resultsDiv").innerHTML = '<div ng-include="" src=" \'sr.html\' "></div>';
read about angularjs $compile function
I don't know why you need to make this JavaScript-call, but its definitely no the 'angular-way'. If you need to conditionally include html, i would recommend using ng-if, ng-hide, ng-show or even ng-switch.
You could do something like this:
// somewhere in your controller
$scope.triggerSomeInclude = true;
// in your template
<div ng-if="triggerSomeInclude">
<div ng-include ="'someFile.html'"></div>
</div>
Another approach would be using a directive. They are the only place, where selecting an element directly could make sense (although even there it usually doesn't to select an element via id). But as I said, it's hard to stay what the best method would be, as I'm not sure what you're trying to achieve.
Although you're not using jQuery, what you're trying to do looks very jQueryesque (awful word) as you're selecting an element directly seemingly totally detached from the $digest and $compile-cycles of angular, so I also would recommend to read this answer:
"Thinking in AngularJS" if I have a jQuery background?
In the end, the method I used was templating example used for ngInclude.
http://docs.angularjs.org/api/ng.directive:ngInclude
Inside my controller, for example, by default it would set the following:
$scope.mainDivTemplate = {url: 'partials/test1.html'}
If I wanted to switch it to something else, I'd call a function that would look a little something like this.
$scope.loadHome = ->
$scope.mainDivTemplate = {url: 'partials/home.html'}
$scope.$apply()
I'm making an in game UI using awesomium, at some points the game loads up and executes a chunk of javascript which is meant to create arbitrary new UI elements. e.g.
jQuery(document.body).append('<span class="game-status-alert">You Lose!</span>');
That works nicely, the problem comes when I want to create some slightly more advanced UI elements, specifically using angular. For example something like:
function ChatBoxControl($scope) { /* Stuff */ }
jQuery(document.body).append(
'<div ng-controller="ChatBoxControl"><div ng-repeat="line in chat"><span>{{line}}</span></div></div>'
);
Not surprisingly, this does not create a new angular view. It simply adds that html to the document and never binds to the ChatBoxControl.
How can I achieve what I'm trying to do here?
You should $compile dynamically added angular content.
Something like:
jQuery(document.body).append(
$compile(
'<div ng-controller="ChatBoxControl"><div ng-repeat="line in chat"><span>{{line}}</span></div></div>'
)(scope)
);
scope for any element you can get using something like:
var scope = angular.element('#dynamicContent').scope();
Also you should get $compile that can be injected in other controller.
See also: AngularJS + JQuery : How to get dynamic content working in angularjs
You might want to use ng-include combined with ng-repeat.
Here is an simple example: http://plunker.no.de/edit/IxB3wO?live=preview
<div ng-repeat="dom in domList" ng-include="dom"></div>
Parent $scope will keep the list of partials loaded into the view.
And ng-repeat + ng-include will iterate over and display partials according
to the list.
When it is the right timing, you can append the partial into the dom list. e.g.
$scope.domList.push("chatbox.html");
(BTW, putting DOM manipulation into controller is not the angular way.)