diff --git a/src/app/ViewCoordinator.qml b/src/app/ViewCoordinator.qml
index 6939b539f0abfbd3fb95d6037a737bf5d475f6f8..6a14c49c88af583ec47e80078024eb748e1be782 100644
--- a/src/app/ViewCoordinator.qml
+++ b/src/app/ViewCoordinator.qml
@@ -74,7 +74,7 @@ QtObject {
     // Create, present, and return a dialog object.
     function presentDialog(parent, path, props = {}) {
         // Open the dialog once the object is created
-        return viewManager.createView(path, parent, function (obj) {
+        return viewManager.createUniqueView(path, parent, function (obj) {
                 const doneCb = function () {
                     viewManager.destroyView(path);
                 };
diff --git a/src/app/ViewManager.qml b/src/app/ViewManager.qml
index 24cf22973edb592afe3e2c7782149cca679b09cf..5a66358aa812c8ff4ecf3b26924f0e32b6df11bc 100644
--- a/src/app/ViewManager.qml
+++ b/src/app/ViewManager.qml
@@ -36,36 +36,70 @@ QtObject {
         }
     }
 
+    // Create a view from a path only if it doesn't already exist. This is used
+    // by the view coordinator to create views that are not self-destructing
+    // (main views) and only exist once per instance of the app.
     function createView(path, parent = null, cb = null, props = {}) {
-        if (views.hasOwnProperty(path)) {
-            // an instance of <path> already exists
+        const component = Qt.createComponent(Qt.resolvedUrl(path));
+        return createViewFromComponent(component, path, parent, cb, props);
+    }
+
+    // Create a new view. Useful when we want to create multiple views that are
+    // self-destructing (dialogs).
+    function createUniqueView(path, parent = null, cb = null, props = {}) {
+        const component = Qt.createComponent(Qt.resolvedUrl(path));
+        return createViewFromComponent(component, getViewName(path), parent, cb,
+                                       props);
+    }
+
+    // Create a new view from a component. If a view with the same path already
+    // exists, it is returned instead.
+    function createViewFromComponent(component, viewName, parent = null,
+                                     cb = null, props = {}) {
+        if (views.hasOwnProperty(viewName)) {
+            // an instance of the view already exists
             if (cb !== null) {
-                cb(views[path])
+                cb(views[viewName])
             }
-            return views[path]
+            return views[viewName]
         }
-        const component = Qt.createComponent(Qt.resolvedUrl(path))
         if (component.status === Component.Ready) {
             const obj = component.createObject(parent, props)
             if (obj === null) {
-                print("error creating object")
+                console.error("error creating object")
                 return null
             }
-            views[path] = obj
+            views[viewName] = obj
             // Set the view name to the object name if it has one.
-            const viewName = obj.objectName.toString() !== '' ? obj.objectName : path.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "")
-            viewPaths[viewName] = path
+            const friendlyName = obj.objectName.toString() !== '' ?
+                obj.objectName :
+                viewName.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "")
+            viewPaths[friendlyName] = viewName
             if (cb !== null) {
                 cb(obj)
             }
-            return views[path]
+            return views[viewName]
         }
-        print("error creating component", path)
+        console.error("error creating component", component.url)
         console.error(component.errorString())
         Qt.exit(1)
         return null
     }
 
+    // Finds a unique view name for a given path by appending a number to the
+    // base name. For example, if a view named "MyView" already exists, the next
+    // view will be named "MyView_1".
+    function getViewName(path) {
+        const baseName = path.replace(/^.*[\\\/]/, '').replace(/\.[^/.]+$/, "")
+        let viewName = baseName
+        let suffix = 1
+        while (views.hasOwnProperty(viewName)) {
+            viewName = `${baseName}_${suffix}`
+            suffix++
+        }
+        return viewName
+    }
+
     function destroyView(path) {
         // The view may already have been destroyed.
         if (!views.hasOwnProperty(path)) {