I have an Angular custom directive which uses a very simple carousel template which only has 2 slides loaded and bound because I expect to repeat lots of them on a page. When the user interacts with the directive I want to load an additional template containing the rest of the slides and compile it under the same scope as everything else in the directive.
This is how I am doing it so far. This function is inside my directive and is called when the user clicks the "next" button.
function loadExtraSlides(){
$templateRequest('/templates/propertyCardExtraSlides.tpl.html').then(function(template) {
$compile($(carouselEl).append(template).contents())($scope);
// Template is loaded
}, function() {
$log.error('Error loading card slides template');
});
}
}
}
This seemed to work at first because the template is loaded and inserted inside the carousel, but unfortunately the new template isn't bound to the scope correctly. If I put {{images}} into the main template is outputs an array of image URLs from my directive's scope. If I put the same thing in my template which is being imported and compiled it just outputs "{{images}}" to the DOM.
Hopefully I'm doing something simple wrong. Any help would be really appreciated.
Related
I have 8 jade view that only one of them is loaded at the time and is filled by jquery into a div which has a controller.
Now, I have 2 question about these:
Does it necessary to define again the controller on top of my partial view(same controller with main controller) ?
All of these views has same ng-click. but after loading they doesn't work. However they work by jquery click event. Should I do any extra thing with them?
I had same problem with li element before, but I resolve it by getting help from ng-click not working from dynamically generated HTML by using compileData but I can't get result with button.
Code:
Main jade:
div(ng-controller="elementCtrl")
div#ddd(class="col-lg-7 col-md-5 col-sm-7")
Partial view sample:
div#spPartial()
div.col-lg-12.col-md-12.col-sm-12
span.col-lg-2.col-md-5.col-sm-5 Name
input#EnglishName(name="name" type="text" ng-model="elementModel.Name" value="#{Name}" class="col-lg-5 col-md-7 col-sm-5")
button(type="button" compile-Data name="btnSaveElement" ng-click="saveElement()") Save
Main part of controller:
//It loads the partial view - It works successfully
$http.post('/api/elements/getElementTypesPartial',
{
"ElementId": elementId,
"ProgramId": newVal,
"ElementTypeId": elementTypeId
})
.success(function (d2) {
$("#ddd").html(d2);
}
//It doesn't work at all
$scope.saveElement = function () {
alert();
alert($scope.elementId);
}
And one additional thing is that I put $scope.saveElement in root of controller scope. I don't have any idea about how angularJs manage $scope, So I see $scope.elementId in client code. Is it right or I should regenerate it($scope.saveElement) every time that partial is loaded?
Sorry I couldn't find any reference which describes these...
You should get rid of the jQuery loading and use an angular router which will load templates based on route configuration.
Since they are loaded by angular, it does all the compiling for you.
The router takes care of the ajax to get the templates automatically also.
Controllers also get defined in the routing config so you would be able to remove ng-controller from the templates
The change over shouldn't take long since setting up routing config is fairly easy to get it started
This would clear up the ng-click problems
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 attempting to add a controller to a dynamically constructed div in angular. However, the controller doesn't seem to be loading and I cannot add corresponding events to the click function.
In the example below, I am constructing this div within a separate parent controller termed 'employeeTableCtrl'. Within the parent controller, when a user clicks the 'more info' button, the new divs are constructed. In the container of this child is where I am looking to attach a new controller.
$scope.moreInfo = function(employee) {
$("<div class='employeeWindow' ng-controller='employeeWindowCtrl'> " +
"<button class='closeButton' ng-click='close()'> x </button> </div>".appendTo("#employees");
}
And in the separate controller I have:
.controller('employeeWindowCtrl', [
'$scope', function ($scope) {
$scope.close = function() {
alert('clicked the x');
}
}
])
The divs are all being constructed correctly, but the the 'employeeWindowCtrl' is not being attached such that my 'click()' function is not being executed.
Does anyone have any tips? Maybe I am approaching this all wrong?
Thanks
What you're looking for is a directive - a chunk of html that has a sort of private controller via the link function. Create the directive in a separate template, place your controller functionality (if it indeed is appropriate for a controller) in the directive's link function and use ng-show to reveal on click. If we had more code to play with I could give a better example of all of this.
https://docs.angularjs.org/guide/directive
I am trying to add an angular JS module inside an already existing code. I'm actually trying to add a new piece of code inside it. The workflow goes like this. When a button is clicked, the JS takes a template and adds it to the dom. In this added template, i would like to insert the new angular JS module. I am trying to atleast show hello world inside the module but haven't been successful.
Let's say when a button is clicked, i'm adding the below tag to the dom
<div patient-details ng-controller='patientDetailsCtrl' id='patientDetails'></div>
This is added through jquery or javascript. How do i make it work with the below directive
angular.module('patientDetailsModule',[])
.directive('patientDetails',function($compile){
return{
//restrict: 'E',
template: "<div>Hello World!!!{{name}}</div>"
};
});
You need to use $compile. $compile() will make sure all the Angular code in your html snippet will be compiled!
Here is an example.
http://plnkr.co/edit/7Wr3oAtvZ8cn31uFFEOs?p=preview
Send Message from nc-click to directive
Directive receives message, compiles html and appends new element
var template = "<div patient-details ng-controller='patientDetailsCtrl' id='patientDetails'>Element added</div>";
var newElement = angular.element(template);
$compile(newElement)(scope);
element.append(newElement);
// can also use element.replaceWith(newElement);
I have this AngularJS app. Everything works just fine.
Now I need to show different pop-ups when specific conditions become true, and I was wondering what would be the best way to proceed.
Currently I’m evaluating two options, but I’m absolutely open to other options.
Option 1
I could create the new HTML element for the pop-up, and append to the DOM directly from the controller.
This will break the MVC design pattern. I’m not happy with this solution.
Option 2
I could always insert the code for all the pop-ups in the static HTML file. Then, using ngShow, I can hide / show only the correct pop-up.
This option is not really scalable.
So I’m pretty sure there has to be a better way to achieve what I want.
Based on my experience with AngularJS modals so far I believe that the most elegant approach is a dedicated service to which we can provide a partial (HTML) template to be displayed in a modal.
When we think about it modals are kind of AngularJS routes but just displayed in modal popup.
The AngularUI bootstrap project (http://angular-ui.github.com/bootstrap/) has an excellent $modal service (used to be called $dialog prior to version 0.6.0) that is an implementation of a service to display partial's content as a modal popup.
It's funny because I'm learning Angular myself and was watching some video's from their channel on Youtube.
The speaker mentions your exact problem in this video https://www.youtube.com/watch?v=ZhfUv0spHCY#t=1681 around the 28:30 minute mark.
It comes down to placing that particular piece of code in a service rather then a controller.
My guess would be to inject new popup elements into the DOM and handle them separate instead of showing and hiding the same element. This way you can have multiple popups.
The whole video is very interesting to watch as well :-)
Create a 'popup' directive and apply it to the container of the popup content
In the directive, wrap the content in a absolute position div along with the mask div below it.
It is OK to move the 2 divs in the DOM tree as needed from within the directive. Any UI code is OK in the directives, including the code to position the popup in center of screen.
Create and bind a boolean flag to controller. This flag will control visibility.
Create scope variables that bond to OK / Cancel functions etc.
Editing to add a high level example (non functional)
<div id='popup1-content' popup='showPopup1'>
....
....
</div>
<div id='popup2-content' popup='showPopup2'>
....
....
</div>
.directive('popup', function() {
var p = {
link : function(scope, iElement, iAttrs){
//code to wrap the div (iElement) with a abs pos div (parentDiv)
// code to add a mask layer div behind
// if the parent is already there, then skip adding it again.
//use jquery ui to make it dragable etc.
scope.watch(showPopup, function(newVal, oldVal){
if(newVal === true){
$(parentDiv).show();
}
else{
$(parentDiv).hide();
}
});
}
}
return p;
});
See
http://adamalbrecht.com/2013/12/12/creating-a-simple-modal-dialog-directive-in-angular-js/
for a simple way of doing modal dialog with Angular and without needing bootstrap
Edit: I've since been using ng-dialog from http://likeastore.github.io/ngDialog which is flexible and doesn't have any dependencies.
Angular-ui comes with dialog directive.Use it and set templateurl to whatever page you want to include.That is the most elegant way and i have used it in my project as well.
You can pass several other parameters for dialog as per need.