4

I currently have a few ng-repeats in my view for building an agenda. Whenever I have a ng-repeat I can include a directive checking if the ng-repeat is done to trigger a method. Works perfect...

The problem is, I have like 5 ng-repeats, I don't want to include the directive for all 5 ng-repeats and check in the method if all 5 have called the method... I just want a way to detect if all my ng-repeats (and other angular stuff) is finished building the view so for example I can put appointments in the agenda via JQuery. Because ofcourse, putting appointments in the agenda (divs) before the agenda (divs) have been created won't work.

Thanks in advance!

UPDATE:

I'm using a REST backend to get the appointments from. So i can't just retrieve the appointments and try to show them in the agenda because the view might not be finished generating (using the ng-repeats)....

So I need something that is triggerd ones the view is done generating (ALL ng-repeats must be done) so i can start placing the appointments.

  • Do you have any demo to see the issue ? – Shidhin Cr May 12 '15 at 14:56
  • 1
    If your appointments are in the form of data (which they should be, leave the formatting to the view) I doubt you're gonna have a problem. What you're describing is more of a JQuery-esque problem where you inject HTML into your DOM. Your ng-repeats know which data they're looking for, and they'll be sure to grab it when they're rendered. – UncleDave May 12 '15 at 14:56
  • I indeed use JQuery to put the appointments (divs) in the correct divs in the agenda. For example the monday 08:00 div will have the unique ID 1-0800. After the agenda has been created i use JQuery to find this div and place the appointment div in that div... – Bas Van Den Heuvel May 12 '15 at 14:59
  • Although angular could happily do that for you - I believe if your JQuery script tag is below your Angular script tag and at the bottom of the body you should be fine. Perhaps also wrap your jquery code in a $(document).ready(function () { }); Also if you'd care to post your code we could perhaps suggest a better way to do some things. – UncleDave May 12 '15 at 15:02
  • @UncleDave How could i use angular to put my appointments in the agenda divs? I have an Array with appointment objects. How can i loop through all appointments in my view (html file) and place them in the correct agenda divs? Ofcourse you can do it like i do right now, in my angular/javascript controller – Bas Van Den Heuvel May 12 '15 at 15:29
  • You could have an array of agenda objects, which each include an array of appointments. The logic you use to sort your appointments into the correct agenda objects should be straight forward. – UncleDave May 12 '15 at 15:32
  • 1
    I would suggest not to do id's manipulation in angular... it can very easily handle such scenarios without going to jquery... – harishr May 12 '15 at 15:43
  • Here, I made you a thing! https://jsfiddle.net/4qzs7rve/3/ You can update $scope.agendas anytime you want (i.e. over REST async) and the view will update. – UncleDave May 12 '15 at 15:55

4 Answers4

1

You should use $viewContentLoaded rather than any directive as this fires after everything in the view loaded. Documentation : https://docs.angularjs.org/api/ngRoute/directive/ngView

Code Example : $scope.$on('$viewContentLoaded', function(event) { // Your Code Goes Here }); Note that this will only work if you are using ng-view from routing.

Moe Shaaban
  • 154
  • 6
  • it sounded very hopefull... To bad i use ui-router so i can have nested views. So im using ui-view instead of ng-view... – Bas Van Den Heuvel May 12 '15 at 15:34
  • This is also available on ui router as per their documentation https://github.com/angular-ui/ui-router/wiki hope that's helpful – Moe Shaaban May 12 '15 at 15:47
  • Looked very hopefull, thanks! The other thing i didnt mention is that my agenda is in a directive with its privet scope. The documentation says: $scope.$on('$viewContentLoaded', function(event){ ... }); Although in a direcitve (private scope with methods in my directive LINK) i have only scope, not $scope. Doesn't work on my "scope" in my directive. – Bas Van Den Heuvel May 12 '15 at 16:02
  • @Kailas send me a real world demo please – Moe Shaaban Nov 17 '15 at 14:03
0

there´s a trick in Angular using a $timeout to delay execution of certain parts of the code until all directives have redered. I'm not sure it will work in this instance but you could try.

In your controller simply add

$timeout(function() {
  // code to execute after directives goes here
});
Patrik Melander
  • 585
  • 3
  • 7
0

You're probably better off not using jQuery to populate the agenda, but using Angular instead. This allows you to just wait until the data is loaded, which is much easier to detect, and Angular will make sure the DOM gets uploaded whenever it can do so.

In your case you can probably do something like this:

Controller:

$scope.days = [];
//Here we create the days for the calendar (7 in this case)
for (var i = 0; i < 7; i++) {
    var hours = [];
    //and the hours, with an empty appointment array for each hour
    for (var i = 0; i < 24; i++) {
        hours.push({ appointments: [] });
    }
    $scope.days.push({
        hours : hours
    }); 
}
//Then we can get the appointments from your api
getAppointments().then(function(appointments) {
    //and add the results to the arrays created above
    appointments.forEach(function(appointment) {
        //This is some simplified logic that only uses the day of the week
        //and hour of the appointment. Your logic would probably a bit more complex 
        //to properly put the appointment in the correct array
        var day = appointment.date.getDay();
        var hour = appointment.date.getHour();
        $scope.days[day].hours[hour].appointments.push(appointment);
    });
});

Template:

<div class="days" ng-repeat="day in days">
    <div class="hours" ng-repeat="hour in day.hours">
        <!-- I assume you have one hours div in which all appointments for that hour will go -->
        <div class="appointments" ng-repeat="appointment in hour">
            {{ appointment.title }}
        </div>

    </div>
</div>

That said, if you really want to detect when the view has finished loading then you have a couple of options:

  1. Wait for all your data being loaded and then use a $timeout to ensure it has been rendered.

It would look something like this:

var somePromise = getPromise();
var someOtherPromise = getOtherPromise();
$q.all([somePromise, someOtherPromise])
    .then(function() {
        //At this point all data is available for angular to render
        $timeout(function() {
            //and now everything should actually be rendered
        });
  1. Listen for the $viewContentLoaded, but this only works if you use ng-view and might fire too early if your data is loaded asynchronous (I'm not entirely sure about the details here, since I usually avoid detecting when the view is loaded).

  2. If all of the above fails you could just continuously check if the desired elements are loaded on the page.

Tiddo
  • 6,331
  • 6
  • 52
  • 85
0

You can use angularjs's directive to make it. With directive you can set the ready event for any dom element.

For more detail, refer to this great post and question.

Community
  • 1
  • 1
LF00
  • 27,015
  • 29
  • 156
  • 295