Search code examples
javascripthtmlangularjscsvpapaparse

Content read in from a .csv file occasionally not showing up on page load


So I'm working on a personal portfolio for myself with a few projects I've done for my intro web dev class. Since we've been practicing data driven content websites and webapps in class, my professor wanted us to do something similar, either by putting our data in a cloud based data storage or in a .csv file. I decided to go the .csv file route.

After creating the .csv file, I'm using Papa Parse to read in the .csv file data into a usable format for my website and then I'm using angular to loop through the data and put the relevant parts on the page. The only section of my website that uses this data is the projects section on the home page.

Anyway, my problem is that sometimes when I load the page, either for the first time when I open the URL, or when I've switched to the home page from the about, or contact page, I've noticed that the content doesn't show up and I have to reload the page to get the gifs and text to show up. Here are some screen shots: What it should look like and What it sometimes looks like. I'll also including a link to my site in the comments (because I don't have 10 reputation yet, so I can't post more than two links) if you'd like to see for yourself. (It's still a work in progress, so I'll admit I'm a little embarrassed about posting it, but I'd really like to solve the problem).

Also, here's the HTML where this data is being used for the page:

<div class="projects">
<h1 class="projects-heading">Projects</h1>
<div class="container projectContainer" ng-repeat="project in projects">
    <div class="row">
        <div class="col-xs-12 col-md-6">
            <img class="projectGif" ng-src="{{project.gifUrl}}" ng-hide="projects.length < 0">
        </div>
        <div class="col-xs-12 col-md-6">
            <h4 class="project-info proj-title">{{project.title}}</h4>
            <p class="project-info proj-body">{{project.description}}</p>
            <a class="project-info" target="_blank" href="{{project.link}}">View the live site</a>
        </div>
    </div>
    <!-- Creates divier line between each separate project -->
    <hr class="project-split">
</div>

My controller:

app.controller('HomeController', function($scope){
Papa.parse("data/home.csv", {
    download: true,
    header: true,
    complete: function(results) {
        $scope.projects = results.data;
    }
});

});


Solution

  • I don't know this Papa but I think this is an asynchronous call therefore it runs outside the Angular loop. Try this

    complete: function(results) {
        $scope.projects = results.data;
        $scope.$apply();
    }
    

    Angular has its own event loop which runs each time Angular knows that it must run. That happens when the code which modifies the state runs within Angular. When the loop runs, all variables, binding and rendering is also updated.

    Here you are using an external library Papa which simply runs an Ajax request. The request is sent within Angular but the result callback is handled outside due to asynchronousity. Therefor you must force Angular to update its data. What $scope.$apply() does is to force the event loop to update only for this controller.

    Remember to do that each time you run code which is not inside Angular but will interact with Angular. That is valid for example for 'onclick' or jQuery events or just any code outside the Angular scope.