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()
Related
I have been trying to use transclusion to create a directive which makes two copies of it's contents and appends them inside the original template. I have failed in my attempts to modify the two copies before they slotted back into the DOM and I think it's because I have misunderstood how transclusion works.
I have another question here which I don't think is going to be answered because I think the premise may be wrong.
Transclude function needs to modify clone properly
I need to take a new approach to this and I was wondering if it would be sensible to ditch transclusion and get my hands dirty inside a compile function.
My new question is, can you take the contents of "elem", make a couple of copies of it using JQlite then compile them manually against the directive's parent scope and add them back into the original template?
So, if my toolbar directive is used like this, where the contents of the toolbar tag can be any HTML the user wants...
<div ng-controller="myController">
<toolbar>
<form name="formName" submit="myController.submit()">
<div>
... some controls...
</div>
</form>
</toolbar>
</div>
And the template for the directive is this....
<toolbar-inner>
<div class="toolbar">
<div transclude-main></div>
</div>
<div class="overflow">
<div transclude-overflow></div>
</div>
</toolbar-inner>
My compile function of the toolbar directive needs to take a copy of the contents of the element, clone it, rename any forms so that we don't have duplicate form names then compile one copy against the parent controller and slot it into the main slot then do the same with a second copy and slot it into the overflow slot.
The key things is that at the end of it I should have a single directive with two copies of it's contents and my controller should have two forms on it - myController.formName and myController.formName2
Please let me know if I haven't explained something correctly here. I'm pretty sure the solution here should not involve transclusion, hence posting the second question. It is not a duplicate.
If I can explain anything in further detail please ask.
Many thanks.
EDIT:
I have tried to do this in the following Plunkr
https://plnkr.co/edit/eUIdaPiOIISDdXGLBTKJ?p=preview
I have a few problems with this:
A) I am getting a JS error in the console - TypeError: Cannot read property 'childNodes' of undefined
B) I was assuming I could just mess with the template in the pre-compile phase and replace the contents of the directive with new HTML consisting of a new template merged with two copies of the original contents. I can see though that I have to compile them against the $parent scope because my directive uses an isolate scope (although not strictly necessary in this cut down example)
C) I get another error when replacing the original contents of the directive element anyway.
I think I am half way there and hopefully this plunk shows what I an prying to achieve, but i have run out of knowledge.
For completeness, here is the plunk where I tried to do it with transclusion, which didn't work because the transcluded contents are already compiled by the time I started messing with them in the transclude function.
https://plnkr.co/edit/XE7REjJRShw43cpfJCh2?p=preview
You can see the full conversation about this in my previous question:
Transclude function needs to modify clone properly
I got your transcluded example working. See here.
I had to call the below to get it working.
$compile(clone)(scope.$parent);
For the ngTransclude:orphan problem, in this version by compiling just the form elements it works when the child transclude is outside of the form.
This plunker was prior to Angular 1.5 which introduce Tranclusion.
link: function(scope, element) {
if (!element.find('ng-transclude').children().length) {
element.find('button').append('<b style="color: red">Button1</b>');
}
}
Plunker
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.
I've recently switched from jQuery to Angularjs and I am in the process of re-coding some pagination logic for the links ("Next", "Previous", etc.) that were written in jQuery-style Javascript previously.
Each link has an ngIf condition (for example, the "Previous" link won't show if you're on page 1) plus an ngClick event, which essentially updates a scope variable called $scope.pagination.position that determines which results are displayed in the table.
My original code was something like this (simplified for clarity):
Template
<a ng-if="pagination.position > 0" ng-click="pagination.first()">First</a>
Controller
$scope.pagination = {
first: function() {
this.position = 0;
}
}
Then I learned more about directives, and how most DOM elements that aren't static HTML should be created using a directive. So I switched each link (since each has it's own display rules and behaviour on clicks) to its own directive, like so:
Template
<a pagination-first></a>
Directive
app.directive('paginationFirst', function() {
return {
link: function(scope,el,attr) {
scope.pagination.first = function() {
scope.pagination.position = 0;
}
},
replace: true,
template: '<a pagination-first ng-if="pagination.position > 0" ng-click="pagination.first()">First</a>'
}
});
I'll cut straight to the chase : am I doing directives wrong? All that's happened, from my perspective, is I've flipped from having logic in my template to having a template in my logic, and I've defined the click event function in the directive rather than in the controller.
Is this even an appropriate time to be using a directive?
I'd like to learn best practices, so I'd love to know if I've missed the point and if the original templated-based ngIf and controller function approach was fine, even with longer and more complex ngIf conditions than the one shown.
If I want to add specific behaviors to a dom or dom list then I normally create a directive. As per angular js perspective the dom manipulation should only be done through directive (For me it is the best place, sometime I have to disobey this due to my lack of knowledge ). I specially found directive use full while creating a widget. In one of my project there was a part where a section is dedicated to display an image and also upload the image. I just use the directive on the top div, with the help of link function I attached the event handlers to various child dom. And as my project doesnot require an isolated scope (as this widget was all used in a single project and the outer scope was under my control) . So it worked like a charm. I cerarted the directive once. And used that widget through rest of the project as it's behavior and design (of the widget ) was same through out the project. For the pagination widget you can create a directive. Take the directive attibutes value as the input of the pagination parameters. Like calling script, limit offset. Container identifier to update the content. Then you can solely concentrate on the pagianation behavior. But from my experience (as I am also not so experienced in angular js), sometimes it becomes a little hectic to develop a directive and and use that throughout the project. As in some places we need to modify the behavior of the directive. And for this it may breaks elsewhere. But I know as I learn more I will be more efficient to handle this kind of situation. Hope my experience will help you.
I am new to angularJs. there is a requirement need to assign css property to component at/from js file level. I have kept debugger, after assign css style to component. In debugger level I can able to see all applied css property to component behavior will be good. Once completes page load, I am not able to see applied css, from js file. From my side may be some overwriting/removing css style. How to achieve this one using angular/JavaScript/J query, great appreciate.
Here is my code.
By AngularJS
angular.element.find('.ctp-textfield')[0].style.width = "75px !important";
angular.element.find('.ctp-textfield')[0]["ng-style"] = "{height: 75px}";
By JavaScript
document.getElementById('Idname').style.width = "75px !important";
By JQuery
$('#idname')[0].style.width = "75px !important";
$('#idname').style.width = "75px !important";
The way to do DOM manipulation in Angular is to use a directive. All of the above snippets of code look like they are not running inside the link function of a directive so will not work as you expect (but theres not enough context to tell what you're doing).
see:
https://docs.angularjs.org/guide/directive
http://www.sitepoint.com/practical-guide-angularjs-directives/
http://www.ng-newsletter.com/posts/directives.html
http://www.befundoo.com/university/tutorials/angularjs-directives-tutorial/
https://github.com/angular/angular.js/wiki/Understanding-Directives
I'm really new to Angular, but learning quickly. However, the one problem that I haven't been able to find an answer for yet is how I can pass around HTML snippets with bindings attached.
e.g. With jQuery I could do something like
var $div = $('<div id="test"><button>CLICK ME!</button></div>');
$div.delegate('button', 'click', function () { alert('CLICKED') });
Then I could pass around this $div variable to other objects. For instance I would use this pattern to separate page specific content from the code of a modal Singleton that encapsulated general functionality.
e.g.
var name = "The Dude";
var $div = $('<div id="test"><button>CLICK ME!</button></div>');
$div.delegate('button', 'click', function () { alert('Hi, ' + name) });
Modal.open({ content: $div});
How can I achieve something similar with Angular?
You should not pass around template code in the controllers, that's not the "angular way". If you have to do DOM manipulation it should stay in a directive. A lot of jQuery developers fall into this trap of thinking like you do with jQuery. But anyways here's how I would solve this problem:
I'm writing this in a directive so it's more modular. You could move this into a controller and it'll work just fine.
Code in plnkr here
In the directive you have a template which contains your code and you can have a ng-click binding which can control a click action to open the modal.
Now as far as the content in the modal is concerned, making the actual template code modular so you can decouple the content from the template depends on if/what angular plugins you're using. They all do something similar but the names may be a little different. For example, if you're using ui-bootstrap(which is awesome by the way, if you dont use any plugins I'd highly recommend it) there's a resolve function that takes a variable as an argument and you can display that in the view. That's exactly what you want to send custom content to the modal(eg. name)