2

I have two route groups, 'anime' and 'manga'. The URLs are either /anime/ or /manga/, but they both share the exact same controllers and templates (the only thing that is different are the color schemes used for each of the templates, but those are decided in a filter that checks whether the particular item being viewed is an anime or a manga):

The anime states definition:

.state('anime', {
    url: "/anime?genres&tags&year&season&page&perpage&sortBy&order",
    templateUrl: "views/titles-index.html",
    controller: 'TitleIndexController',
    data: {
        type: 'anime'
    },
    ncyBreadcrumb: {
        label: 'Anime'
    }
}).state('anime-detail', {
    url: "/anime/:id/:slug",
    controller: 'TitleDetailController',
    templateUrl: "views/titles-detail.html",
    ncyBreadcrumb: {
        parent: 'anime-index',
        label: '{{item.title_main}}'
    }
}).state('anime-detail.anime-reviews', {
    url: '/reviews',
    controller: 'TitleReviewsController',
    templateUrl: 'views/titles-reviews.html',
    ncyBreadcrumb: {
        label: 'Reviews'
    }

The manga state definition:

}).state('manga', {
    url: "/manga?genres&tags&year&season&page&perpage&sortBy&order",
    templateUrl: "views/titles-index.html",
    controller: 'TitleIndexController',
    data: {
        type: 'manga'
    },
    ncyBreadcrumb: {
        label: 'Manga'
    }
}).state('manga-detail', {
    url: "/manga/:id/:slug",
    controller: 'TitleDetailController',
    templateUrl: "views/titles-detail.html",
    ncyBreadcrumb: {
        parent: 'manga-index',
        label: '{{item.title_main}}'
    }
}).state('manga-detail.manga-reviews', {
    url: '/reviews',
    controller: 'TitleReviewsController',
    templateUrl: 'views/titles-reviews.html',
    ncyBreadcrumb: {
        label: 'Reviews'
    }
})

As you can see, there already is a lot of repetition in this, which I don't like at all. The repetition is only going to increase as I keep adding new routes (you can already see manga-reviews and anime-reviews, which there will be a lot more of).

Another problem is that I have to use long names, such as manga-detail, anime-detail instead of plain 'detail'.

I thought about implementing a simpler style, such as /browse/ and /browse/?view=anime but that looks uglier and I'll also have problems with the ncyBreadcrumbs, as the index is not a direct parent of the detail.

Having /anime/ and /manga/ urls is way more user-friendly, too, but if anyone has a better idea, I would love to switch, as long as it gets rid of the repetition.

I have to use this for ui-sref:

ui-sref="{{item.title_type}}-detail({id: item.id, slug: slugify(item.title_main)})"

Which barely works, for children states it doesn't work at all.

I've been hitting my head against the wall with the way my router is structured and to be quite honest, I couldn't get past this problem so I'm a little stuck right now and would appreciate any kind of help.

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
marekpw
  • 662
  • 2
  • 5
  • 19

1 Answers1

3

There is a working plunker

Solution here, is suprisingly simple, and you've almost been there. We replace the 'anime' or/and 'manga' with a param - e.g. :oneForBoth

.state('oneForBoth', {
    url: "/:oneForBoth?genres&tags&year&season&page&perpage&sortBy&order",
    templateUrl: "views/titles-index.html",
    controller: 'TitleIndexController',
    data: {
      // should be $stateParams.oneForBoth
      //type: 'anime'
    },
    ncyBreadcrumb: {
      label: '{{$stateParams.oneForBoth}}'
    }
}).state('oneForBoth-detail', {
    url: "/:oneForBoth/:id/:slug",
    controller: 'TitleDetailController',
    templateUrl: "views/titles-detail.html",
    ncyBreadcrumb: {
      parent: 'oneForBoth',
      label: '{{item.title_main}}'
    }
}).state('oneForBoth-detail.oneForBoth-reviews', {
    url: '/reviews',
    controller: 'TitleReviewsController',
    templateUrl: 'views/titles-reviews.html',
    ncyBreadcrumb: {
      label: 'Reviews'
    }

And now, from user perspective (and also from the 'ncy-angular-breadcrumb' perspective)

<a href="#/manga">
<a href="#/manga/theId/theSlug">
<a href="#/manga/theId/theSlug/reviews">

<a href="#/anime">
<a href="#/anime/theId/theSlug">
<a href="#/anime/theId/theSlug/reviews">

Check it here

As Dylan Watt pointed out, this would support any value for 'oneForBoth'. So we can put in some restrictions as discussed here:

Matching url with array list of words in AngularJS ui-router

Here is the updated plunker

And these is our extend code, which supports just anime and manga

.state('oneForBoth', {
    url: "/{oneForBoth:(?:anime|manga)}?genres&tags&year&season&page&perpage&sortBy&order",
    templateUrl: "views/titles-index.html",
    controller: 'TitleIndexController',
    data: {
      // should be $stateParams.oneForBoth
      //type: 'anime'
    },
    ncyBreadcrumb: {
      label: '{{$stateParams.oneForBoth}}'
    }

Where the most important part is restriction over the url:

url: "/{oneForBoth:(?:anime|manga)}?

Check that here

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • It's worth pointing out that this solution means any value will work. `#/profile/theId/theSlug` would still bring you there. No url hash will fail, it will always try and map to this. – Dylan Watt May 17 '15 at 17:24
  • @DylanWatt give me sec... it is intereting what you say... give me sec – Radim Köhler May 17 '15 at 17:26
  • I'm not amazing at regex, but I think you could use the following: url: "/{oneForBoth:^(anime|manga)}/:id/:slug". Going by the regex route matching here: https://github.com/angular-ui/ui-router/wiki/URL-Routing – Dylan Watt May 17 '15 at 17:33
  • 2
    @DylanWatt I **extended** my answer with solution, also **updated plunker** and provided some **more links** with details.. thanks for pointing that out. Hope this could the OP help a bit ;) – Radim Köhler May 17 '15 at 17:35
  • Thank you so much everyone. You guys have just made my day, I've been ripping my hair out over this for a good couple of days. I'm saved. – marekpw May 17 '15 at 17:49
  • Great to see that sir! Enjoy mighty UI-Router ;) – Radim Köhler May 17 '15 at 17:50