1

I am building a user interface similar to Google Drive or Dropbox. As a user, I should be able to click on a folder and view all files and folders nested within. When I do so, the current folder should be reflected in the url (e.g. home/:folderId). I should be able to repeat this process ad infinitum (e.g. home/:folderId/:folderId:/folderId). Each :folderId should be a child state of its parent folder.

Using ui-router, I am currently able to get workspace/my-workspace/:folderId, where my-workspace displays all root level folders and files. When I click on a folder I can see all nested files and folders. However, when I click on a nested folder, a new state is created for the child folder but it replaces the state for the parent folder. Further, The :folderId is not appended to the url, but rather replaces it (e.g. home/123 becomes home/456 instead of home/123/456).

How can this be done? Below is a trimmed down version of my config block.


.config(function config($urlRouterProvider, $stateProvider) {
  $urlRouterProvider.when('/workspace', '/workspace/my-workspace');

  var workspace = {
    name: 'workspace',
    url: '/workspace',
    views: {
      '': {
        templateUrl: 'workspace.partial.html',
        controller: 'WorkspaceController',
        controllerAs: 'workspace'
      },
      'header@workspace': {
        templateUrl: 'header.partial.html'
      },
      'leftPanel@workspace': {
        templateUrl: 'left-panel.partial.html'
      },
      'mainPanel@workspace': {
        templateUrl: 'main-panel.partial.html'
      }
    },
    resolve: {
      workspace: function workspace(WorkspaceService) {
        var workspace;

        return WorkspaceService.getWorkspace()
          .then(function(response) {
            workspace = response.data;
            return workspace;
          });
      }
    }
  };

  var myWorkspace = {
    name: 'myWorkspace',
    url: '/my-workspace',
    parent: 'workspace',
    views: {
      'main@workspace': {
        templateUrl: 'my-workspace.partial.html',
        controller: 'MyWorkspaceController',
        controllerAs: 'myWorkspace'
      }
    },
    resolve: {
      myWorkspace: function(workspace, WorkspaceService) {
        var myWorkspace;

        return WorkspaceService.getMyWorkspace()
          .then(function(response) {
            myWorkspace = response.data;
            myWorkspace.folders.forEach(function(folder) {
              folder.sourceType = 'folder';
            });

            return myWorkspace;
          });
      }
    }
  };

  var folder = {
    name: 'folder',
    url: '/:folderId',
    parent: 'myWorkspace',
    views: {
      'main@workspace': {
        // reuses myWorkspace template
        templateUrl: 'my-workspace.partial.html',
        controller: 'MyWorkspaceFolderController'
      }
    },
    resolve: {
      folder: function(WorkspaceService, $stateParams) {
        var folderId = $stateParams.folderId,
            folder;

        return WorkspaceService.getFolder(folderId)
          .then(function(response) {
            folder = response.data;
            folder.folders.forEach(function(folder) {
              folder.sourceType = 'folder';
            });
            return folder;
          });
      }
    }
  };

  $stateProvider
    .state(workspace)
    .state(myWorkspace)
    .state(folder);
});
Forest Toney
  • 48
  • 1
  • 4

1 Answers1

0

Before you will get better answer, there is different solution. There is related Q & A and here its plunker

we should take the state folder:

var folder = {
    name: 'folder',
    url: '/:folderId',

and the expectation to have:

home/:folderId/:folderId:/folderId

And change the requirement to have state like this:

<a href="#/home/Folder1">
<a href="#/home/Folder1/SubFolder1/">
<a href="#/home/Folder1/SubFolder1/SubFolderA">
<a href="#/home/Folder1/SubFolder1/SubFolderB">
<a href="#/home/Folder1/SubFolder2/SubFolderX">

to be represented by ONE parameter folderPath

var folder = {
    name: 'folder',
    url: '/{folderPath:[a-zA-Z0-9/]*}',

check the Q & A

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335