Подтвердить что ты не робот

Angularjs - Скрыть содержимое до загрузки DOM

У меня проблема в Angularjs, где в моем HTML есть мерцание, прежде чем мои данные вернутся с сервера.

Вот видео, демонстрирующее проблему: http://youtu.be/husTG3dMFOM - обратите внимание на # | и серая область справа.

Я пробовал ngCloak без каких-либо успехов (хотя ngCloak не позволяет появляться в скобках как обещано), и мне интересно, как лучше всего скрыть контент, пока HTML не будет заполнен Angular.

Я получил его для работы с этим кодом в контроллере:

var caseCtrl = function($scope, $http, $routeParams) {
    $('#caseWrap').hide(); // hides when triggered using jQuery
    var id = $routeParams.caseId;

    $http({method: 'GET', url: '/v1/cases/' + id}).
        success(function(data, status, headers, config) {                   
            $scope.caseData = data;

            $('#caseWrap').show(); // shows using jQuery after server returns data
        }).
        error(function(data, status, headers, config) {
            console.log('getCase Error', arguments);
        });
}

... но я снова и снова слышал, чтобы не манипулировать DOM с контроллера. Мой вопрос: как я могу достичь этого, используя директиву? Другими словами, как я могу скрыть элемент, к которому прикреплена директива, пока все содержимое не будет загружено с сервера?

4b9b3361

Ответ 1

В CSS добавьте:

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
  display: none !important;
}

и просто добавьте атрибут ng-cloak "в ваш div, как здесь:

<div id="template1" ng-cloak>{{scoped_var}}<div>

doc: https://docs.angularjs.org/api/ng/directive/ngCloak

Ответ 2

На вашем элементе caseWrap введите ng-show="contentLoaded", а затем, где у вас есть $('#caseWrap').show();, поставьте $scope.contentLoaded = true;

Если элемент caseWrap находится вне этого контроллера, вы можете делать то же самое, используя $rootScope или события.

Ответ 3

Добавьте в свой CSS следующее:

[ng\:cloak],[ng-cloak],.ng-cloak{display:none !important}

Компиляция ваших шаблонов angular не выполняется достаточно быстро.

UPDATE

Вам не следует выполнять манипуляции с DOM в контроллере. Есть две вещи, которые вы можете сделать... 1. Вы можете перехватывать изменения в значение в пределах объема контроллера через директиву! В вашем случае создайте директиву как атрибут, которому присвоено свойство, которое вы хотите посмотреть. В вашем случае это будет caseData. Если casedata ложно, скройте его. В противном случае покажите его.

  1. Проще всего использовать ngShow = 'casedata'.

код

var myApp = angular.module('myApp', []);
myApp.controller("caseCtrl", function ($scope, $http, $routeParams, $timeout) {
    $scope.caseData = null;
    //mimic a delay in getting the data from $http
    $timeout(function () {
        $scope.caseData = 'hey!';
    }, 1000);

})
    .directive('showHide', function () {
    return {
        link: function (scope, element, attributes, controller) {
            scope.$watch(attributes.showHide, function (v) {
                if (v) {
                    element.show();
                } else {
                    element.hide();
                }
            });
        }
    };
});

HTML

<div ng-controller='caseCtrl' show-hide='caseData'>using directive</div>
<div ng-controller='caseCtrl' ng-show='caseData'>using ngShow</div>

JSFIDDLE: http://jsfiddle.net/mac1175/zzwBS/

Ответ 4

Поскольку вы попросили директиву, попробуйте это.

.directive('showOnLoad', function() {
  return {
    restrict: 'A',
    link: function($scope,elem,attrs) {

      elem.hide();

      $scope.$on('show', function() {
        elem.show();
      });

    }
  }
});

Придерживайтесь (show-on-load) в своем элементе, а в вашем контроллере вводите $rootScope и используйте это широковещательное событие при загрузке html.

$rootScope.$broadcast('show');

Ответ 5

Я использовал ответ Zack для создания директивы 'loading', которая может быть полезна некоторым людям.

Шаблон:

<script id="ll-loading.html" type="text/ng-template">
  <div layout='column' layout-align='center center'>
    <md-progress-circular md-mode="indeterminate" value="" md-diameter="52"></md-progress-circular>
  </div>
</script>

Директива:

    directives.directive('loading', function() {
  return {
    restrict: 'E',
    template: 'll-loading.html',
    link: function($scope,elem,attrs) {

      elem.show();

      $scope.$on('loaded', function() {
        console.log("loaded: ");
        elem.hide();
      });

    }
  }
});

В этом примере используется angular -материал в html

Ответ 6

Принятый ответ не помог мне. У меня были некоторые элементы, которые имели ng-show директивы, и элементы все равно отображались бы на мгновение даже с ng-cloak. Похоже, что ng-cloak был разрешен до появления ng-show false. Добавление класса ng-hide в мои элементы исправило мою проблему.