Затримка маршруту AngularJS змінюється до завантаження моделі для запобігання мерехтіння


321

Мені цікаво, чи існує спосіб (як у Gmail) для AngularJS затримати показ нового маршруту до того моменту, поки кожна модель та її дані не будуть отримані за допомогою відповідних сервісів.

Наприклад, якби там було ProjectsControllerвказано список усіх проектів, і project_index.htmlякий був шаблоном, який показував ці проекти, Project.query()він буде вилучений повністю перед тим, як показати нову сторінку.

До цього часу стара сторінка все ще не відображатиметься (наприклад, якщо я переглядав іншу сторінку, а потім вирішив переглянути цей проектний індекс).

Відповіді:


374

Властивість рішення $ routeProvider дозволяє затримувати зміну маршруту до завантаження даних.

Спочатку визначте маршрут із таким resolveатрибутом.

angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/phones', {
        templateUrl: 'partials/phone-list.html', 
        controller: PhoneListCtrl, 
        resolve: PhoneListCtrl.resolve}).
      when('/phones/:phoneId', {
        templateUrl: 'partials/phone-detail.html', 
        controller: PhoneDetailCtrl, 
        resolve: PhoneDetailCtrl.resolve}).
      otherwise({redirectTo: '/phones'});
}]);

зауважте, що resolveвластивість визначена на маршруті.

function PhoneListCtrl($scope, phones) {
  $scope.phones = phones;
  $scope.orderProp = 'age';
}

PhoneListCtrl.resolve = {
  phones: function(Phone, $q) {
    // see: https://groups.google.com/forum/?fromgroups=#!topic/angular/DGf7yyD4Oc4
    var deferred = $q.defer();
    Phone.query(function(successData) {
            deferred.resolve(successData); 
    }, function(errorData) {
            deferred.reject(); // you could optionally pass error data here
    });
    return deferred.promise;
  },
  delay: function($q, $defer) {
    var delay = $q.defer();
    $defer(delay.resolve, 1000);
    return delay.promise;
  }
}

Зауважте, що визначення контролера містить об'єкт розділення, який оголошує речі, які повинні бути доступні конструктору контролера. Тут phonesінжектор вводиться в контролер і визначається у resolveвластивості.

The resolve.phonesФункція відповідає за повернення обіцянки. Усі обіцянки зібрані, а зміна маршруту затягується до тих пір, поки всі обіцянки не будуть вирішені.

Робоча демонстрація: http://mhevery.github.com/angular-phonecat/app/#/phones Джерело: https://github.com/mhevery/angular-phonecat/commit/ba33d3ec2d01b70eb5d3d531619bf90153496831


10
@MiskoHevery - що робити, якщо ваші контролери знаходяться всередині модуля і визначаються як рядок, а не функція. Як ви могли налаштувати атрибут рішення, як ви?
aar0n

53
Як це використовується в angular.controller()визначеннях контролерів типу? У $routeProviderматеріалі, я думав, вам доведеться використовувати назви рядків контролерів.
Бен Леш

6
Будь-який приклад із використанням angular.controller () та з останньою версією AngularJS?
Лоран

22
@blesh, коли ви використовуєте angular.controller(), ви можете призначити результат цієї функції змінної ( var MyCtrl = angular.controller(...)), а потім працювати з цим далі ( MyCtrl.loadData = function(){..}). Перегляньте відео з яєчком
petrkotek

17
Я все ще хотів би приємно обійтися, не розміщуючи свій контролер у глобальному масштабі. Я не хочу всюди займатися глобалами. Ви можете це робити з постійною, але було б непогано мати можливість увімкнути функцію роздільної здатності на / в контролері, а не деінде.
Ерік Гонн

51

Ось мінімальний робочий приклад, який працює для Angular 1.0.2

Шаблон:

<script type="text/ng-template" id="/editor-tpl.html">
    Editor Template {{datasets}}
</script>

<div ng-view>

</div>

JavaScript:

function MyCtrl($scope, datasets) {    
    $scope.datasets = datasets;
}

MyCtrl.resolve = {
    datasets : function($q, $http) {
        var deferred = $q.defer();

        $http({method: 'GET', url: '/someUrl'})
            .success(function(data) {
                deferred.resolve(data)
            })
            .error(function(data){
                //actually you'd want deffered.reject(data) here
                //but to show what would happen on success..
                deferred.resolve("error value");
            });

        return deferred.promise;
    }
};

var myApp = angular.module('myApp', [], function($routeProvider) {
    $routeProvider.when('/', {
        templateUrl: '/editor-tpl.html',
        controller: MyCtrl,
        resolve: MyCtrl.resolve
    });
});​

http://jsfiddle.net/dTJ9N/3/

Упорядкована версія:

Оскільки $ http () вже повертає обіцянку (він же відкладений), насправді нам не потрібно створювати власну. Таким чином, ми можемо спростити MyCtrl. вирішити:

MyCtrl.resolve = {
    datasets : function($http) {
        return $http({
            method: 'GET', 
            url: 'http://fiddle.jshell.net/'
        });
    }
};

Результат $ http () містить дані , статус , заголовки та конфігураційні об'єкти, тому нам потрібно змінити тіло MyCtrl на:

$scope.datasets = datasets.data;

http://jsfiddle.net/dTJ9N/5/


Я намагаюся зробити щось подібне, але маю проблеми з введенням "наборів даних", оскільки це не визначено. Будь-які думки?
Роб Біграйв

Гей MB21, я думаю , ви могли б допомогти мені з цим питанням: stackoverflow.com/questions/14271713 / ...
winduptoy

Чи може хтось допомогти мені перетворити цю відповідь у формат app.controller ("MyCtrl")? jsfiddle.net/5usya/1 не працював для мене.
користувач1071182

я отримую помилку:Unknown provider: datasetsProvider <- datasets
chovy

Ви можете зробити свою відповідь простішою, замінивши набори даних цим:function($http) { return $http({method: 'GET', url: '/someUrl'}) .then( function(data){ return data;}, function(reason){return 'error value';} ); }
Morteza Tourani

32

Я бачу, як деякі люди запитують, як це зробити за допомогою методу angular.controller із введенням залежності у полегшення до мінімуму. Оскільки я щойно працював над цим, я почував себе зобов’язаним повернутися та допомогти. Ось моє рішення (прийняте з оригінального питання та відповіді Місько):

angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/phones', {
        templateUrl: 'partials/phone-list.html', 
        controller: PhoneListCtrl, 
        resolve: { 
            phones: ["Phone", "$q", function(Phone, $q) {
                var deferred = $q.defer();
                Phone.query(function(successData) {
                  deferred.resolve(successData); 
                }, function(errorData) {
                  deferred.reject(); // you could optionally pass error data here
                });
                return deferred.promise;
             ]
            },
            delay: ["$q","$defer", function($q, $defer) {
               var delay = $q.defer();
               $defer(delay.resolve, 1000);
               return delay.promise;
              }
            ]
        },

        }).
      when('/phones/:phoneId', {
        templateUrl: 'partials/phone-detail.html', 
        controller: PhoneDetailCtrl, 
        resolve: PhoneDetailCtrl.resolve}).
      otherwise({redirectTo: '/phones'});
}]);

angular.controller("PhoneListCtrl", [ "$scope", "phones", ($scope, phones) {
  $scope.phones = phones;
  $scope.orderProp = 'age';
}]);

Оскільки цей код походить від запитання / найпопулярнішої відповіді, він не перевірений, але він повинен відправити вас у правильному напрямку, якщо ви вже розумієте, як зробити зручне кутовий код для мінімізації. Тією частиною, якої не вимагав мій власний код, було введення "Телефон" у функцію дозволу для "телефонів", і я взагалі не використовував жодного "затримки".

Я також рекомендую це відео YouTube http://www.youtube.com/watch?v=P6KITGRQujQ&list=UUKW92i7iQFuNILqQOUOCrFw&index=4&feature=plcp , яке мені дуже допомогло

Якщо вас це зацікавить, я вирішив також вставити власний код (Написаний у coffeescript), щоб ви могли побачити, як я працював.

FYI, заздалегідь я використовую загальний контролер, який допомагає мені робити CRUD на кількох моделях:

appModule.config ['$routeProvider', ($routeProvider) ->
  genericControllers = ["boards","teachers","classrooms","students"]
  for controllerName in genericControllers
    $routeProvider
      .when "/#{controllerName}/",
        action: 'confirmLogin'
        controller: 'GenericController'
        controllerName: controllerName
        templateUrl: "/static/templates/#{controllerName}.html"
        resolve:
          items : ["$q", "$route", "$http", ($q, $route, $http) ->
             deferred = $q.defer()
             controllerName = $route.current.controllerName
             $http(
               method: "GET"
               url: "/api/#{controllerName}/"
             )
             .success (response) ->
               deferred.resolve(response.payload)
             .error (response) ->
               deferred.reject(response.message)

             return deferred.promise
          ]

  $routeProvider
    .otherwise
      redirectTo: '/'
      action: 'checkStatus'
]

appModule.controller "GenericController", ["$scope", "$route", "$http", "$cookies", "items", ($scope, $route, $http, $cookies, items) ->

  $scope.items = items
      #etc ....
    ]

Чи правильно випливаю з вашого прикладу та моїх невдалих спроб, що тепер неможливо посилатися на resolveфункцію в контролері, в останніх версіях Angular? Отже, це має бути оголошено правильно в конфігурації, як тут?
XML

@XMLilley Я майже впевнений, що це так. Цей приклад був з 1.1.2, коли я його писав, я вважаю. Я не побачив жодної документації щодо введення рішення у контролер
bitwit

2
Класно, спасибі. Є багато прикладів цього на SO (наприклад, перші два тут), але вони всі з 2012 і початку 2013 року. Це елегантний підхід, але, здається, застарів. Найчистішою альтернативою зараз, здається, є написання окремих служб, які є об'єктами обіцянки.
XML

Дякую, це працювало на мене. Для всіх, хто отримує помилки щодо невизначеного $deferсервісу, зауважте, що у версії 1.5.7 AngularJS ви хочете використовувати його $timeoutзамість.
racl101

18

Цей документ , який є частиною версії 1.1.5 і вище, відкриває $promiseоб'єкт $resource. Версії ngResource, включаючи цю комісію, дозволяють вирішувати такі ресурси:

$ routeProvider

resolve: {
    data: function(Resource) {
        return Resource.get().$promise;
    }
}

контролер

app.controller('ResourceCtrl', ['$scope', 'data', function($scope, data) {

    $scope.data = data;

}]);

Які версії включають цю комісію, будь ласка?
XML

Найновіша нестабільна версія (1.1.5) включає цей документ. ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js
Максиміліан Гофман

Мені подобається цей менш дослівний підхід. Було б непогано створити обіцянку від фактичного об’єкта даних і передати це безпосередньо, але це настільки мало коду, що він працює добре.
Сем Барнум

1
Як ресурс отримає доступ до $ routeParams? Наприклад: in GET '/api/1/apps/:appId'-> App.get({id: $routeParams.appId}).$promise();Я не можу використовувати так
zeronone

2
@zeronone ви вводите $routeрішення та використовуєте $route.current.params. Будьте обережні, $routeParamsвсе ще вказує на старий маршрут.
Бріс Стейсі

16

Цей фрагмент коду є впровадженням залежностей дружнього (я навіть використовувати його в комбінації ngmin і спотворювати ) , і це більш елегантним домен керованого рішення на базі.

Наведений нижче приклад реєструє ресурс телефону та постійний phoneRoutes , який містить всю інформацію про маршрутизацію для цього домену (телефону). Щось мені не сподобалось у наданій відповіді, було розташування логіки вирішення - головний модуль не повинен нічого знати і не турбуватися про те, як аргументи ресурсів надаються контролеру. Таким чином логіка залишається в одному домені.

Примітка: якщо ви використовуєте ngmin (а якщо ні: вам слід), вам слід записати функції вирішення лише за допомогою конвенції DI масиву.

angular.module('myApp').factory('Phone',function ($resource) {
  return $resource('/api/phone/:id', {id: '@id'});
}).constant('phoneRoutes', {
    '/phone': {
      templateUrl: 'app/phone/index.tmpl.html',
      controller: 'PhoneIndexController'
    },
    '/phone/create': {
      templateUrl: 'app/phone/edit.tmpl.html',
      controller: 'PhoneEditController',
      resolve: {
        phone: ['$route', 'Phone', function ($route, Phone) {
          return new Phone();
        }]
      }
    },
    '/phone/edit/:id': {
      templateUrl: 'app/phone/edit.tmpl.html',
      controller: 'PhoneEditController',
      resolve: {
        form: ['$route', 'Phone', function ($route, Phone) {
          return Phone.get({ id: $route.current.params.id }).$promise;
        }]
      }
    }
  });

Наступним фрагментом є введення даних про маршрутизацію, коли модуль перебуває у конфігураційному стані, та застосування його до $ routeProvider .

angular.module('myApp').config(function ($routeProvider, 
                                         phoneRoutes, 
                                         /* ... otherRoutes ... */) {

  $routeProvider.when('/', { templateUrl: 'app/main/index.tmpl.html' });

  // Loop through all paths provided by the injected route data.

  angular.forEach(phoneRoutes, function(routeData, path) {
    $routeProvider.when(path, routeData);
  });

  $routeProvider.otherwise({ redirectTo: '/' });

});

Тестування конфігурації маршруту за допомогою цієї установки також досить легко:

describe('phoneRoutes', function() {

  it('should match route configuration', function() {

    module('myApp');

    // Mock the Phone resource
    function PhoneMock() {}
    PhoneMock.get = function() { return {}; };

    module(function($provide) {
      $provide.value('Phone', FormMock);
    });

    inject(function($route, $location, $rootScope, phoneRoutes) {
      angular.forEach(phoneRoutes, function (routeData, path) {

        $location.path(path);
        $rootScope.$digest();

        expect($route.current.templateUrl).toBe(routeData.templateUrl);
        expect($route.current.controller).toBe(routeData.controller);
      });
    });
  });
});

Ви можете побачити це з повною славою в моєму останньому (майбутньому) експерименті . Хоча цей метод для мене добре працює, мені дуже цікаво, чому інжектор $ не затримує побудову нічого, коли виявляє введення нічого, що є об'єктом обіцянки ; це зробило б речі soooOOOOOooOOOOO набагато простішими.

Редагувати: використано Angular v1.2 (rc2)


2
Ця відмінна відповідь здається набагато більше відповідно до "кутової" філософії (інкапсуляція тощо). Нам усім слід докладати зусиль, щоб логіка не повзала по кодовій базі, як kudzu.
zakdances

I really wonder why the $injector isn't delaying construction of anything when it detects injection of anything that is a promise objectЯ здогадуюсь, що вони опустили цю функціональність, оскільки це може заохочувати шаблони дизайну, які негативно впливають на чуйність додатків. Ідеальний додаток на їх думку - це справді асинхронний, тому вирішення має бути кращим випадком.
zakdances

11

Затримка показу маршруту, безумовно, призведе до асинхронного клубка ... чому б просто не відстежувати стан завантаження вашої основної сутності та використовувати його у поданні. Наприклад, у контролері ви можете використовувати як зворотній зв'язок, так і помилку виклику в ngResource:

$scope.httpStatus = 0; // in progress
$scope.projects = $resource.query('/projects', function() {
    $scope.httpStatus = 200;
  }, function(response) {
    $scope.httpStatus = response.status;
  });

Тоді в полі ви можете зробити все, що завгодно:

<div ng-show="httpStatus == 0">
    Loading
</div>
<div ng-show="httpStatus == 200">
    Real stuff
    <div ng-repeat="project in projects">
         ...
    </div>
</div>
<div ng-show="httpStatus >= 400">
    Error, not found, etc. Could distinguish 4xx not found from 
    5xx server error even.
</div>

6
Можливо, виставлення HTTP-статусу перегляду не вірно, більше, ніж спілкування з класами CSS та елементами DOM належить до контролера. Я, мабуть, використовував би ту саму ідею, але абстрактний статус відсутній у isValid () та isLoaded ().
jpsimons

1
Це дійсно не найкраще розділення проблем, плюс те, що воно вийде з ладу, якщо ви вкладете контролери, які залежать від конкретного об'єкта.
null

Це досить розумно .. що стосується викриття коду статусу перегляду, ви можете просто дотримуватися http логіки у властивостях сфери в межах контролера, а потім прив'язувати їх. Крім того, якщо ви робите кілька дзвінків ajax, які відбуваються у фоновому режимі, ви все одно захочете це зробити.
KingOfHypocrites

Це було б добре, якби питання було просто затримкою перегляду. Але роздільну здатність найкраще використовувати, якщо вам потрібно затримати екземпляр контролера - не лише перегляд. (Наприклад: Якщо вам потрібно бути впевненим, що ваш JSON завантажений, тому що ваш контролер передає його директиві ще до його проведення.) З документів: "маршрутизатор буде чекати, коли всі вони будуть вирішені, або один буде відхилений до того, як контролер буде примірник ".
Дан

8

Я працював над кодом Міско вище, і це те, що я зробив з ним. Це більш сучасне рішення, оскільки $deferвоно було змінено на $timeout. Підставивши $timeoutпроте чекатиме в протягом періоду тайм - ауту (в коді Мисько, в 1 секунду), а потім повернути дані в надії , що це вирішені вчасно. Таким чином він повертається якнайшвидше.

function PhoneListCtrl($scope, phones) {
  $scope.phones = phones;
  $scope.orderProp = 'age';
}

PhoneListCtrl.resolve = {

  phones: function($q, Phone) {
    var deferred = $q.defer();

    Phone.query(function(phones) {
        deferred.resolve(phones);
    });

    return deferred.promise;
  }
}

7

Використання AngularJS 1.1.5

Оновлення функції "телефони" у відповіді Юстен за допомогою синтаксису AngularJS 1.1.5 .

Оригінал:

phones: function($q, Phone) {
    var deferred = $q.defer();

    Phone.query(function(phones) {
        deferred.resolve(phones);
    });

    return deferred.promise;
}

Оновлено:

phones: function(Phone) {
    return Phone.query().$promise;
}

Набагато коротше, завдяки команді Angular та учасникам програми. :)

Це також відповідь Максиміліана Гофмана. Мабуть, цей комітет перетворився на 1.1.5.


1
Я, здається, нічого не можу знайти $promiseв документах . Можливо, було виведено з версії v2.0 +.
zakdances

Доступний лише у 1.2
Томасі

5

Ви можете використовувати властивість $ routeProvider resolution для відстрочки зміни маршруту до завантаження даних.

angular.module('app', ['ngRoute']).
  config(['$routeProvider', function($routeProvider, EntitiesCtrlResolve, EntityCtrlResolve) {
    $routeProvider.
      when('/entities', {
        templateUrl: 'entities.html', 
        controller: 'EntitiesCtrl', 
        resolve: EntitiesCtrlResolve
      }).
      when('/entity/:entityId', {
        templateUrl: 'entity.html', 
        controller: 'EntityCtrl', 
        resolve: EntityCtrlResolve
      }).
      otherwise({redirectTo: '/entities'});
}]);

Зауважте, що resolve властивість визначена в маршруті.

EntitiesCtrlResolveі EntityCtrlResolveє постійними об'єктами, визначеними в тому ж файлі, як EntitiesCtrlі EntityCtrlконтролери.

// EntitiesCtrl.js

angular.module('app').constant('EntitiesCtrlResolve', {
  Entities: function(EntitiesService) {
    return EntitiesService.getAll();
  }
});

angular.module('app').controller('EntitiesCtrl', function(Entities) {
  $scope.entities = Entities;

  // some code..
});

// EntityCtrl.js

angular.module('app').constant('EntityCtrlResolve', {
  Entity: function($route, EntitiesService) {
    return EntitiesService.getById($route.current.params.projectId);
  }
});

angular.module('app').controller('EntityCtrl', function(Entity) {
  $scope.entity = Entity;

  // some code..
});

3

Мені подобається ідея darkporter, тому що колективу розробників, новому в AngularJS, буде зрозуміти і працювати відразу.

Я створив цю адаптацію, яка використовує 2 діви, один для панелі завантажувача та інший для фактичного вмісту, що відображається після завантаження даних. Помилка обробки буде зроблена в іншому місці.

Додайте прапор "готового" до області "$":

$http({method: 'GET', url: '...'}).
    success(function(data, status, headers, config) {
        $scope.dataForView = data;      
        $scope.ready = true;  // <-- set true after loaded
    })
});

У перегляді html:

<div ng-show="!ready">

    <!-- Show loading graphic, e.g. Twitter Boostrap progress bar -->
    <div class="progress progress-striped active">
        <div class="bar" style="width: 100%;"></div>
    </div>

</div>

<div ng-show="ready">

    <!-- Real content goes here and will appear after loading -->

</div>

Дивіться також: Документи панелі прогресу Boostrap


Трохи розпадається, якщо ви завантажуєте кілька фрагментів даних. Як дізнатися, чи все завантажено?
toxaq

З моменту, коли я додав цю відповідь у лютому, справи продовжувались, на цій сторінці значно активніше. Схоже, в Angular є краща підтримка для вирішення цієї проблеми зараз, ніж пропонується тут.
Привіт

Я приїжджаю трохи пізно, але робота з декількома даними не викликає особливих проблем. Вам просто потрібно використовувати окремі змінні (booleans: isReadyData1, isReadyData2 тощо) для кожного запиту та встановити $ range.ready = isReadyData1 && isReadyData2 ...; добре працює для мене.
GuillaumeA

1

Мені сподобалися відповіді вище, і я багато чого навчився з них, але є щось, чого не вистачає у більшості вищезазначених відповідей.

Я застряг у подібному сценарії, коли я розв’язував URL-адресу з деякими даними, які отримуються в першому запиті від сервера. Проблема, з якою я стикався, полягала в тому, що якщо обіцянка є rejected.

Я використовую для користувача постачальник , який використовується для повернення , Promiseякий було вирішено resolveв $routeProviderтой час фази конфігурації.

Я хочу наголосити на тому, що це поняття whenробить щось подібне.

Він бачить URL в рядку url, а потім відповідний whenблок в називаному контролері і перегляд віднесений настільки добре.

Скажімо, у мене є такий фазовий код конфігурації.

App.when('/', {
   templateUrl: '/assets/campaigns/index.html',
   controller: 'CampaignListCtr',
   resolve : {
      Auth : function(){
         return AuthServiceProvider.auth('campaign');
      }
   }
})
// Default route
.otherwise({
   redirectTo: '/segments'
});

У кореневій URL-адресі браузера в першому блоці запуску дзвонять інакше otherwise.

Давайте уявимо сценарій, коли я натискаю rootUrl в адресному рядку, AuthServicePrivider.auth()викликається функція.

Скажімо, Обіцянка повернулася в стані відхилення, що тоді ???

Нічого не виводиться взагалі.

Otherwise блок не буде виконуватися так, як це стосується будь-якого URL-адреси, який не визначений у конфігураційному блоці і невідомий для фази configure angularJs.

Нам доведеться впоратися з подією, яку звільняють, коли ця обіцянка не буде вирішена. При невдачі $routeChangeErorrзвільняється$rootScope .

Його можна захопити, як показано в коді нижче.

$rootScope.$on('$routeChangeError', function(event, current, previous, rejection){
    // Use params in redirection logic.
    // event is the routeChangeEvent
    // current is the current url
    // previous is the previous url
    $location.path($rootScope.rootPath);
});

IMO Як правило, це гарна ідея помістити код відстеження подій у запущений блок програми. Цей код запускається відразу після фази налаштування програми.

App.run(['$routeParams', '$rootScope', '$location', function($routeParams, $rootScope, $location){
   $rootScope.rootPath = "my custom path";
   // Event to listen to all the routeChangeErrors raised
   // by the resolve in config part of application
   $rootScope.$on('$routeChangeError', function(event, current, previous, rejection){
       // I am redirecting to rootPath I have set above.
       $location.path($rootScope.rootPath);
   });
}]);

Таким чином, ми можемо впоратися з обіцяними помилками під час фази налаштування.


0

У мене був складний багаторівневий інтерфейс розсувної панелі з вимкненим шаром екрану. Створення директиви щодо відключення екранного шару, яка б створила подію клацання для виконання такого стану

$state.go('account.stream.social.view');

створювали ефект мерехтіння history.back () замість цього спрацював нормально, проте в моєму випадку це не завжди в історії. Так що я дізнаюся, що якщо я просто створюю атрибут href на моєму екрані відключення замість state.go, працював як шарм.

<a class="disable-screen" back></a>

Директива "назад"

app.directive('back', [ '$rootScope', function($rootScope) {

    return {
        restrict : 'A',
        link : function(scope, element, attrs) {
            element.attr('href', $rootScope.previousState.replace(/\./gi, '/'));
        }
    };

} ]);

app.js Я просто зберігаю попередній стан

app.run(function($rootScope, $state) {      

    $rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) {         

        $rootScope.previousState = fromState.name;
        $rootScope.currentState = toState.name;


    });
});

-2

Одним з можливих рішень може бути використання директиви ng-cloak з елементом, де ми використовуємо моделі, наприклад

<div ng-cloak="">
  Value in  myModel is: {{myModel}}
</div>

Я думаю, що для цього потрібно менше зусиль.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.