Programming

AngularJS UI 라우터-상태를 다시로드하지 않고 URL 변경

procodes 2020. 7. 3. 22:10
반응형

AngularJS UI 라우터-상태를 다시로드하지 않고 URL 변경


현재 우리 프로젝트는 default $routeProvider를 사용하고 있으며 url페이지를 다시로드하지 않고 변경하기 위해이 "핵"을 사용하고 있습니다

services.service('$locationEx', ['$location', '$route', '$rootScope', function($location, $route, $rootScope) {
    $location.skipReload = function () {
        var lastRoute = $route.current;
        var un = $rootScope.$on('$locationChangeSuccess', function () {
            $route.current = lastRoute;
            un();
        });
        return $location;
    };
    return $location;
}]);

그리고 controller

$locationEx.skipReload().path("/category/" + $scope.model.id).replace();

내가 대체 생각하고 routeProvider함께 ui-router중첩 경로에 대한,하지만의를 찾을 수 없습니다 ui-router.

가능 angular-ui-router합니까?

왜 이것이 필요합니까? 내가 예와 함께 설명 보자
경로를 새로운 카테고리를 만드는 것은 /category/newclickingSAVE I 쇼에 success-alert내가 경로 변경하려는 /category/new/caterogy/23(23 - DB에 저장된 새 항목의 ID입니다)


간단히 $state.transitionTo 대신 사용할 수 있습니다 $state.go . 내부적으로 $state.go 호출 $state.transitionTo 하지만 자동으로 옵션을로 설정합니다 { location: true, inherit: true, relative: $state.$current, notify: true } . 전화를 걸고 $state.transitionTo 설정할 수 있습니다 notify: false . 예를 들면 다음과 같습니다.

$state.go('.detail', {id: newId}) 

에 의해 대체 될 수있다

$state.transitionTo('.detail', {id: newId}, {
    location: true,
    inherit: true,
    relative: $state.$current,
    notify: false
})

편집 : fracz가 제안한대로 간단히 다음과 같습니다.

$state.go('.detail', {id: newId}, {notify: false}) 

좋아, 해결 :) Angular UI Router에는이 새로운 메소드 $ urlRouterProvider.deferIntercept () https://github.com/angular-ui/ui-router/issues/64가 있습니다.

기본적으로 이것은 다음과 같습니다.

angular.module('myApp', [ui.router])
  .config(['$urlRouterProvider', function ($urlRouterProvider) {
    $urlRouterProvider.deferIntercept();
  }])
  // then define the interception
  .run(['$rootScope', '$urlRouter', '$location', '$state', function ($rootScope, $urlRouter, $location, $state) {
    $rootScope.$on('$locationChangeSuccess', function(e, newUrl, oldUrl) {
      // Prevent $urlRouter's default handler from firing
      e.preventDefault();

      /** 
       * provide conditions on when to 
       * sync change in $location.path() with state reload.
       * I use $location and $state as examples, but
       * You can do any logic
       * before syncing OR stop syncing all together.
       */

      if ($state.current.name !== 'main.exampleState' || newUrl === 'http://some.url' || oldUrl !=='https://another.url') {
        // your stuff
        $urlRouter.sync();
      } else {
        // don't sync
      }
    });
    // Configures $urlRouter's listener *after* your custom listener
    $urlRouter.listen();
  }]);

이 방법은 현재 angular ui router 마스터 버전 (선택적 매개 변수가있는 btw) 에만 포함되어 있다고 생각합니다 . 소스를 사용하여 복제하고 빌드해야합니다.

grunt build

문서는 다음을 통해 소스에서도 액세스 할 수 있습니다.

grunt ngdocs

(/ site 디렉토리에 내장 됨) // README.MD의 추가 정보

동적 매개 변수 (사용하지 않은)에 의해 이것을 수행하는 다른 방법이있는 것 같습니다 . nateabele에 많은 크레딧.


참고로, 여기 에 Angular UI Router의 $ stateProvider의 선택적 매개 변수 가 있습니다.

angular.module('myApp').config(['$stateProvider', function ($stateProvider) {    

  $stateProvider
    .state('main.doorsList', {
      url: 'doors',
      controller: DoorsListCtrl,
      resolve: DoorsListCtrl.resolve,
      templateUrl: '/modules/doors/doors-list.html'
    })
    .state('main.doorsSingle', {
      url: 'doors/:doorsSingle/:doorsDetail',
      params: {
        // as of today, it was unclear how to define a required parameter (more below)
        doorsSingle: {value: null},
        doorsDetail: {value: null}
      },
      controller: DoorsSingleCtrl,
      resolve: DoorsSingleCtrl.resolve,
      templateUrl: '/modules/doors/doors-single.html'
    });

}]);

그 중 하나는 매개 변수 중 하나가 누락 된 경우에도 상태를 해결할 수 있다는 것입니다. SEO는 한 가지 목적, 가독성입니다.

위의 예에서 doorsSingle이 필수 매개 변수가되기를 원했습니다. 그것들을 정의하는 방법은 명확하지 않습니다. 여러 선택적 매개 변수와 함께 작동하므로 실제로 문제가되지 않습니다. 토론은 여기 https://github.com/angular-ui/ui-router/pull/1032#issuecomment-49196090


이 문제와 함께 많은 시간을 보낸 후 여기에 내가 일한 것이 있습니다.

$state.go('stateName',params,{
    // prevent the events onStart and onSuccess from firing
    notify:false,
    // prevent reload of the current state
    reload:false, 
    // replace the last record when changing the params so you don't hit the back button and get old params
    location:'replace', 
    // inherit the current params on the url
    inherit:true
});

이 설정은 다음과 같은 문제를 해결했습니다.

  • 에서 URL을 업데이트 할 때 교육 컨트롤러를 두 번 호출되지 않습니다 .../.../123
  • The training controller is not getting invoked again when navigating to another state

State configuration

state('training', {
    abstract: true,
    url: '/training',
    templateUrl: 'partials/training.html',
    controller: 'TrainingController'
}).
state('training.edit', {
    url: '/:trainingId'
}).
state('training.new', {
    url: '/{trainingId}',
    // Optional Parameter
    params: {
        trainingId: null
    }
})

Invoking the states (from any other controller)

$scope.editTraining = function (training) {
    $state.go('training.edit', { trainingId: training.id });
};

$scope.newTraining = function () {
    $state.go('training.new', { });
};

Training Controller

var newTraining;

if (!!!$state.params.trainingId) {

    // new      

    newTraining = // create new training ...

    // Update the URL without reloading the controller
    $state.go('training.edit',
        {
            trainingId : newTraining.id
        },
        {
            location: 'replace', //  update url and replace
            inherit: false,
            notify: false
        });     

} else {

    // edit

    // load existing training ...
}   

If you need only change url but prevent change state:

Change location with (add .replace if you want to replace in history):

this.$location.path([Your path]).replace();

Prevent redirect to your state:

$transitions.onBefore({}, function($transition$) {
 if ($transition$.$to().name === '[state name]') {
   return false;
 }
});

i did this but long ago in version: v0.2.10 of UI-router like something like this::

$stateProvider
  .state(
    'home', {
      url: '/home',
      views: {
        '': {
          templateUrl: Url.resolveTemplateUrl('shared/partial/main.html'),
          controller: 'mainCtrl'
        },
      }
    })
  .state('home.login', {
    url: '/login',
    templateUrl: Url.resolveTemplateUrl('authentication/partial/login.html'),
    controller: 'authenticationCtrl'
  })
  .state('home.logout', {
    url: '/logout/:state',
    controller: 'authenticationCtrl'
  })
  .state('home.reservationChart', {
    url: '/reservations/?vw',
    views: {
      '': {
        templateUrl: Url.resolveTemplateUrl('reservationChart/partial/reservationChartContainer.html'),
        controller: 'reservationChartCtrl',
        reloadOnSearch: false
      },
      'viewVoucher@home.reservationChart': {
        templateUrl: Url.resolveTemplateUrl('voucher/partial/viewVoucherContainer.html'),
        controller: 'viewVoucherCtrl',
        reloadOnSearch: false
      },
      'addEditVoucher@home.reservationChart': {
        templateUrl: Url.resolveTemplateUrl('voucher/partial/voucherContainer.html'),
        controller: 'voucherCtrl',
        reloadOnSearch: false
      }
    },
    reloadOnSearch: false
  })

Calling

$state.go($state.current, {myParam: newValue}, {notify: false});

will still reload the controller.

To avoid it, you have to declare the parameter as dynamic:

$stateProvider.state({
    name: 'myState',
    url: '/my_state?myParam',
    params: {
        myParam: {
          dynamic: true,
        }
    },
    ...
});

Then you don't even need the notify, just calling

$state.go($state.current, {myParam: newValue})

suffices. Neato!

From the documentation:

When dynamic is true, changes to the parameter value will not cause the state to be entered/exited. The resolves will not be re-fetched, nor will views be reloaded.

[...]

This can be useful to build UI where the component updates itself when the param values change.


Try something like this

$state.go($state.$current.name, {... $state.params, 'key': newValue}, {notify: false})

I don't think you need ui-router at all for this. The documentation available for the $location service says in the first paragraph, "...changes to $location are reflected into the browser address bar." It continues on later to say, "What does it not do? It does not cause a full page reload when the browser URL is changed."

So, with that in mind, why not simply change the $location.path (as the method is both a getter and setter) with something like the following:

var newPath = IdFromService;
$location.path(newPath);

The documentation notes that the path should always begin with a forward slash, but this will add it if it's missing.

참고URL : https://stackoverflow.com/questions/23585065/angularjs-ui-router-change-url-without-reloading-state

반응형