Loading component in template driven form submit


#1

So I’ve got a template driven form and I’d like to give some feedback to the user when they press the submit button. I wanted to do this with a Loading component, but calling the dismiss() function on it later in the function doesn’t work. It also throws an error.

This is the code I’m using for the function that gets called by (ngSubmit):

    postForm(value: any) {
        let loading = Loading.create({
            content: "Submitting answers...",
        });
        this.nav.present(loading);
        for (var question in value) {

            if (value.hasOwnProperty(question)) {
                var qID = parseInt(question);
                var answer = value[question];
                this.backend.answerQuestion(qID, answer);
            }

        }
        loading.dismiss();
    }

This is the error that shows up in the console:

4     726810   group    EXCEPTION: Error during evaluation of "ngSubmit"
5     726812   error    EXCEPTION: Error during evaluation of "ngSubmit"
6     726815   error    ORIGINAL EXCEPTION: TypeError: leavingView.pageRef(...) is undefined
7     726816   error    ORIGINAL STACKTRACE:
8     726817   error    LoadingMdPopOut@http://localhost:8100/build/js/app.bundle.js:42372:19
[360]</Transition</Transition.createTransition@http://localhost:8100/build/js/app.bundle.js:62333:16
[303]</NavController</NavController.prototype._beforeTrans/<@http://localhost:8100/build/js/app.bundle.js:44829:34
Zone</ZoneDelegate</ZoneDelegate.prototype.invoke@http://localhost:8100/build/js/angular2-polyfills.js:390:20
Zone</Zone</Zone.prototype.run@http://localhost:8100/build/js/angular2-polyfills.js:283:25
[194]</NgZoneImpl</NgZoneImpl.prototype.runOuter@http://localhost:8100/build/js/app.bundle.js:28187:60
[193]</NgZone</NgZone.prototype.runOutsideAngular@http://localhost:8100/build/js/app.bundle.js:28105:65
[303]</NavController</NavController.prototype._beforeTrans@http://localhost:8100/build/js/app.bundle.js:44819:9
[303]</NavController</NavController.prototype._postRender@http://localhost:8100/build/js/app.bundle.js:44801:9
[303]</NavController</NavController.prototype._render@http://localhost:8100/build/js/app.bundle.js:44717:13
[303]</NavController</NavController.prototype._transition@http://localhost:8100/build/js/app.bundle.js:44689:9
[303]</NavController</NavController.prototype.remove@http://localhost:8100/build/js/app.bundle.js:44550:13
[311]</ViewController</ViewController.prototype.dismiss@http://localhost:8100/build/js/app.bundle.js:46142:16
[9]</Profile</Profile.prototype.postForm@http://localhost:8100/build/js/app.bundle.js:523:9
anonymous/ChangeDetector_Profile_0.prototype.handleEventInternal@viewFactory_Profile:229:17
[111]</AbstractChangeDetector</AbstractChangeDetector.prototype.handleEvent@http://localhost:8100/build/js/app.bundle.js:13891:24
anonymous/ChangeDetector_Profile_0.prototype.hydrateDirectives/this.outputSubscriptions[0]<.next<@viewFactory_Profile:260:102
[195]</EventEmitter</EventEmitter.prototype.subscribe/schedulerFn</<@http://localhost:8100/build/js/app.bundle.js:28314:94
Zone</ZoneDelegate</ZoneDelegate.prototype.invokeTask@http://localhost:8100/build/js/angular2-polyfills.js:423:24
NgZoneImpl/this.inner<.onInvokeTask@http://localhost:8100/build/js/app.bundle.js:28145:32
Zone</ZoneDelegate</ZoneDelegate.prototype.invokeTask@http://localhost:8100/build/js/angular2-polyfills.js:422:24
Zone</Zone</Zone.prototype.runTask@http://localhost:8100/build/js/angular2-polyfills.js:320:29
ZoneTask/this.invoke@http://localhost:8100/build/js/angular2-polyfills.js:490:29

9     726818   error    ERROR CONTEXT:

#2

@Pharetra I guess that you’re calling the dismiss() method too quickly, i.e. before the component is loaded, therefore I would recommend you to update your code this way:

    postForm(value: any) {
        let loading = Loading.create({
            content: "Submitting answers...",
        });
        this.nav.present(loading).then(() => {
            for (var question in value) {

                if (value.hasOwnProperty(question)) {
                    var qID = parseInt(question);
                    var answer = value[question];
                    this.backend.answerQuestion(qID, answer);
                }

            }

            loading.dismiss();
        });
    }

#3

How does backend.answerQuestion work? I’m assuming it’s not synchronous. Does this matter to you?


#4

That worked, thanks!

@rapropos That is correct, it’s an asynchronous call.


#5

Thanks I was facing the same issue too. I was calling the dismiss() before the loading component gets loaded.


#6

Then you might want to look into collecting all the calls to the backend into a Promise.all wrapper or an Observable equivalent, if your goal is to have the loading component be visible until the answers have been recorded at the server.