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);
});