Angular ui-router: child state controller not gett

2019-08-31 04:06发布

问题:

In my Angular app, I have the following route structure:

.state('mapping', {
    url: '/mapping',
    templateUrl: 'app/components/mapping/mapping.html',
    controller: 'MapCtrl as map',
    abstract: true,
    authenticate: true
})
.state('mapping.all', {
    url: '',
    templateUrl: 'app/components/mapping/partials/all.html',
    authenticate: true
})
.state('mapping.project', {
    url: '/:projectName',
    templateUrl: 'app/components/mapping/partials/project.html',
    controller: 'ProjectCtrl as proj',
    authenticate: true
})

When accessing the mapping state, mapping.all loads by default. It basically shows a list of projects which link to the mapping.project state, as such:

<a ui-sref="mapping.project({projectId: project.id, projectName: project.name})">...</a>

I want to call the ProjectCtrl when I access mapping.project in order to load the necessary data, but it never even gets loaded. In the snippet below which includes only relevant data, the alert message never pops up:

angular
    .module('watera')
    .controller('ProjectCtrl', Controller);

Controller.$inject = ['$stateParams', 'UserFactory', 'ProjectFactory'];

function Controller($stateParams, UserFactory, ProjectFactory) {
    var proj = this;

    activate();

    function activate() {
        alert('1');
    }
}

The js file is correctly linked and the controller is named correctly. The <div ui-view></div> element is placed within mapping.html, as seen below:

<div id="ribbon" class="no-print">
    <div class="container-fluid">
        <div class="row">
            <div class="col-xs-12">
                <strong>Mapping</strong>
                <p class="text-muted">In this section...</p>
            </div>
        </div>
    </div>
</div>

<div ui-view></div>

Why is this controller not loading?

EDIT: It gets weirder, I switched the structure to:

.state('mapping', {
    url: '/mapping',
    templateUrl: 'app/components/mapping/mapping.html',
    abstract: true,
    authenticate: true
})
.state('mapping.all', {
    url: '',
    templateUrl: 'app/components/mapping/partials/all.html',
    controller: 'MapCtrl as map',
    authenticate: true
})
.state('mapping.project', {
    url: '/:projectName',
    templateUrl: 'app/components/mapping/partials/project.html',
    controller: 'ProjectCtrl as proj',
    authenticate: true
})

And while MapCtrl keeps working correctly, ProjectCtrl still doesn't.

回答1:

Found the issue... There were two instances of ProjectCtrl in this project:

Apparently, this causes some sort of silent conflict because there was absolutely no console error. Since the second instance was also linked on index.html, after the one that I wanted to load, it was probably simply replacing the correct version. Debugging nightmare.

Fixed now.



回答2:

An abstract state cannot exist by definition so having a template URL for the parent and the children (which won't inherit the parent's templateUrl because the children define their own) is highly dubious IMO.

Im also wondering if there is trouble distinguising between ... url: '' AND url: '/:projectName'

(Although it should handle the distinction). However, to make sure I suggest a step-by-step approach. Kick off with the following mapping I suggest and then enhance it from there ...

.state('mapping', {
    abstract: true,
    authenticate: true
})
.state('mapping.all', {
    url: '/',
    templateUrl: 'app/components/mapping/partials/all.html',
    controller: 'MapCtrl as map',
})
.state('mapping.project', {
    url: '/project/:projectName',
    templateUrl: 'app/components/mapping/partials/project.html',
    controller: 'ProjectCtrl as proj',
})