swagger-api / swagger-ui

Swagger UI is a collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API.
https://swagger.io
Apache License 2.0
26.47k stars 8.96k forks source link

DeepLinking breaks angular 8 routing #5811

Open kubarskii opened 4 years ago

kubarskii commented 4 years ago

Hi, I have a very annoying problem with angular 8 and swagger deepLinking feature, which i want to use for sharing exact tag/operation description.

My swagger-UI configuration options: this.ui = SwaggerUIBundle({ url: "http://petstore.swagger.io/v2/swagger.json", domNode: this.el.nativeElement.querySelector('.swagger-container'), deepLinking: true, filter: true, presets: [ SwaggerUIBundle.presets.apis, ], validatorUrl: null, plugins: [ ... ], docExpansion: 'none', displayOperationId: true });

The problem is: When the deepLinkng is set to true, the deep-linking plugin helper (setHash), overrides the url: host/pathname to host/#/tag-clicked.

hanyi0121 commented 4 years ago

hi,i have same issue,Have you solved it

leshkin commented 4 years ago

hi,i have same issue,Have you solved it

I've monkey patched this issue: https://stackoverflow.com/questions/56180836/is-there-a-way-to-prefix-deeplinking-fragment-of-swagger-ui/59957196#59957196

hanyi0121 commented 4 years ago

hi,i have same issue,Have you solved it

I've monkey patched this issue: https://stackoverflow.com/questions/56180836/is-there-a-way-to-prefix-deeplinking-fragment-of-swagger-ui/59957196#59957196

Thank you very much,it works.

kubarskii commented 4 years ago

I solved it by creating statePlugin and wrapping show action

statePlugins: {
        layout: {
          wrapActions: {
            show: (ori, {getConfigs, layoutSelectors}) => (...args) => {
              ori(...args);
              if (!getConfigs().deepLinking) {
                return;
              }

              const createDeepLinkPath = (str) => str.trim();
              const setHash = (value) => {
                if (value) {
                  return history.replaceState(null, null, `${this.route.routeConfig.path}#${value}`);
                } else {
                  return window.location.hash = '';
                }
              };

              try {
                let [tokenArray, shown] = args;
                tokenArray = Array.isArray(tokenArray) ? tokenArray : [tokenArray];
                const urlHashArray = layoutSelectors.urlHashArrayFromIsShownKey(tokenArray); // Will convert

                // No hash friendly list?
                if (!urlHashArray.length) {
                  return;
                }

                const [type, assetName] = urlHashArray;

                if (!shown) {
                  return setHash('/');
                }

                if (urlHashArray.length === 2) {
                  setHash(createDeepLinkPath(`/${encodeURIComponent(type)}/${encodeURIComponent(assetName)}`));
                } else if (urlHashArray.length === 1) {
                  setHash(createDeepLinkPath(`/${encodeURIComponent(type)}`));
                }
              } catch (e) {
                console.error(e); // eslint-disable-line no-console
              }
            }
          }
        }
      }
rmannibucau commented 4 years ago

+1 to fix this, it prevents to embed swagger-ui in any html5 router based SPA (angular, react, vue) until swagger-ui is deployed at root itself.