javascriptjsonbackbone.jsrequire

Backbone insert data inside Model from another


I have a simple app in backbone where the logic isn't clear for me, It's my second app and I don't know if is good the logic and how I have construct it.
The goal is when I load a page I want to retrieve all folders and files of a specific directory and print it.
I have create an app general where I include another app called Folder. When I load the page I create the general app, search inside a folder and retireve folders and files into a json with an ajax function.
I have succesfull do that but my problem is how now populate my FolderView, FolderModel and Folder Collection? Is necessary to do that I think but I don't know how to pass this json to FolderCollection/FOlderModel.

This is my appView

define(['jquery' , 'backbone', 'views/folder', 'models/folder', 'collections/folder', 'models/app'], 
    function($, Backbone, FolderView, FolderModel, FolderCollection, AppModel){
    var AppView = Backbone.View.extend({
        model: AppModel,
        el:$('#folder'),

        initialize: function(){
            console.log('initialize AppView');
            this.retrievFolderFile('uploads');
            //prendo le cartelle e le metto nel json

            this.folders = new FolderCollection();
            this.render();
            //this.todos.bind('sync', this.render, this);
            //this.todos.fetch();
        },
        render: function(){
            var element = this.$el;
            element.html('');
            this.folders.each(function(model){
                var folderView = new FolderView({model:model});

                element.append(folderView.el);
            });
        },
        retrievFolderFile: function(dir){
            var here = this;
            console.log('retrieveFolderFile');
            $.ajax({
                type: "POST",
                dataType: "json",
                data: {"dir": dir},
                url: 'function/retrieve_folder.php',
                success: function(data) {
                    console.log(data);
// ------------------ HERE I HAVE RESULT HOW TO PASS TO FOLDER VIEW/ COLLECTION?------
                }
            });
        }
    })

    return AppView;
});

This is my folderModel

define(['backbone'],function(Backbone){
    var FolderModel = Backbone.Model.extend({
        defaults:{
            name:'Folder',
            path:''
        },
        initialize:function(){
            console.log('Initialized Folder model');
        }
    });

    return FolderModel;
});

This is my FolderCollection

define(['backbone', 'models/folder'], function(Backbone, FolderModel){

    var folderCollection = Backbone.Collection.extend({
        model: FolderModel,
    });

    return folderCollection;
});

This is my FolderView

define(['jquery', 'underscore', 'backbone', 'text!templates/folder.html'], function($, _, Backbone, FolderTemplate){
    var FolderView = Backbone.View.extend({
        el:$('#folder'),
        template: _.template(FolderTemplate),

        initialize: function(){
            console.log('FolderView initialized');
            this.render();
        },
        render: function(){
            console.log('FolderView render');

            //$(this.el).html(this.template({model: this.options.model}));
        }
    });

    return FolderView;
});

To retrieve folder and files I use this file PHP that return me a valid json to backbone

<?php
$dir = $_POST['dir'];
$data = fillArrayWithFileNodes( new DirectoryIterator( '../'.$dir ) );

function fillArrayWithFileNodes( DirectoryIterator $dir )
{
  $data = array();
  foreach ( $dir as $node )
  {
    if ( $node->isDir() && !$node->isDot() )
    {
        //$data[$node->getFilename()] = fillArrayWithFileNodes( new DirectoryIterator( $node->getPathname() ) );
        $arr_to_insert = array();
        $arr_to_insert['name'] = $node->getFilename();
        $arr_to_insert['type'] = 'folder';
        array_push($data, $arr_to_insert);
    }
    else if ( $node->isFile() )
    {
      //$data[] = $node->getFilename();
        $arr_to_insert = array();
        $arr_to_insert['name'] = $node->getFilename();
        $arr_to_insert['type'] = 'file';
        array_push($data, $arr_to_insert);
    }
  }
  return $data;
}
echo json_encode($data);
?>

How to pass from appview the json that return me? Is correct to do the folderand filde search inside appview or I have to do it inside folderModel? Because after when I click on a folder I want to retrieve its file and folders again. Help me to understand the logic and how to pass it. I thought to call a function inside FolderCollection like parseFolderFile and insert it into a model but how?

Thanks


Solution

  • AJAX is asynchronous.. So you are making an ajax call and then calling the render method which is iterating over the collection and renders them.

    But your data is not ready until and after the sucess callback, where I guess your collection will be populated. So you are supposed to populate the collection inside the success call back and then call render.

    So something in these lines

    initialize: function () {
        console.log('initialize AppView');
        this.folders = new FolderCollection();
        this.retrievFolderFile('uploads');
    },
    render: function () {
        var element = this.$el;
        element.html('');
        this.folders.each(function (model) {
            var folderView = new FolderView({
                model: model
            });
            element.append(folderView.el);
        });
    },
    retrievFolderFile: function (dir) {
        var here = this;
        console.log('retrieveFolderFile');
        $.ajax({
            type: "POST",
            dataType: "json",
            data: {
                "dir": dir
            },
            url: 'function/retrieve_folder.php',
            success: function (data) {
                console.log(data);
                here.folders.set(data);
                here.render();
            }
        });
    }
    

    Also why do you want to handle an ajax request , where there is already a native one provided by backbone.

    You can declare the url in the collection do this.folders.fetch() , and then listen to the sync or the resent event which will be lot more cleaner in my view.

    Using native Fetch

    define(['jquery', 'backbone', 'views/folder', 'models/folder',
                                 'collections/folder', 'models/app'],
    
    function ($, Backbone, FolderView, FolderModel,
                                    FolderCollection, AppModel) {
        var AppView = Backbone.View.extend({
            model: AppModel,
            el: $('#folder'),
    
            initialize: function () {
                this.folders = new FolderCollection();
                // This will automatically call the render once the 
                // collection is reset 
                this.listenTo(this.folders, 'reset', this.render);
                this.folders.data = 'uploads';
                this.folders.fetch();
            },
            render: function () {
                var element = this.$el;
                element.html('');
                this.folders.each(function (model) {
                    var folderView = new FolderView({
                        model: model
                    });
    
                    element.append(folderView.el);
                });
            }
        })
    
        return AppView;
    });
    
    define(['backbone', 'models/folder'], function(Backbone, FolderModel){
    
        var folderCollection = Backbone.Collection.extend({
            model: FolderModel,
            url : 'function/retrieve_folder.php' + this.data;
        });
    
        return folderCollection;
    });