2014-10-22 4 views
2

В моем шаблоне у меня есть что-то вроде этого:функция вызывается несколько раз из шаблона

{{formatMyDate(date)}} 

но date переменная сфера, которая не доступна немедленно, так это выражение будет вызывать функцию formatMyDate() много раз (возвращение undefined) перед возвратом правильного значения.

я мог проверить, если date не равно нулю в пределах функции, но я предполагаю, что это будет более чистым НЕ вызывать функцию вообще, если date является null.

Любой способ достичь этого? Может ли наш пользовательский фильтр помочь мне?

EDIT:
Было высказано предположение о том, что такое поведение может быть нормальным, в зависимости от $ переваривать цикла.
Затем я установил scope.$watch, чтобы проверить, сколько раз изменяется значение date.
Обратите внимание, что я определяю их в директиве.

scope.$watch('date', function(value){ 
    console.log('watched_date: ' + value) 
}) 

и я ввел console.log() на моей formatMyDate функции, а также

scope.formatMyDate = function(date){ 
    console.log("called_date: " + date) 
    return dateService.format(date, 'YYYY-MM-DD') 
} 

Проверка консоли я получаю (псевдокод)

called_date: undefined 
watched_date: undefined 
called_date: undefined // many many times (around 20/30) 
called_date: correctValue //2 or 3 times 
watched_date: correctValue 
called_date: correctValue //other 3/4 times 

Я если это все еще связано с циклом $digest или это ошибка в моем коде

+1

Возможно, одноразовая привязка будет соответствовать вашим потребностям, если вы находитесь на Угловом> = 1.3. Проверьте это [здесь] (https://docs.angularjs.org/guide/expression). –

+0

@NikosParaskevopoulos спасибо, но нет, я вынужден использовать версию 1.0.8 – Leonardo

+1

Любая функция, вызываемая непосредственно из выражения или косвенно через ngRepeat/ngOptions (и тому подобное), потенциально будет вызываться несколько раз. Вот как работают угловые работы (см. [$ Digest] (https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$digest)). Тем не менее, я думаю, что всегда полезно добавить форматирование в выделенные фильтры. Вы проверили [фильтр даты] (https://docs.angularjs.org/api/ng/filter/date)? – Yoshi

ответ

7

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

Либо использовать date $filter или, если вы делаете что-то очень уникальное и дату $filter не достаточно хорош для вас, то вы можете создать свой собственный $filter, как это:

app.filter('formatMyDate', function() { 
    return function (date) { 
     if (!date) return ""; 
     var result; 
     //your code here  
     return result; 
    }; 
}); 

И использовать его, как это в шаблоне:

{{date | formatMyDate}} 

UPDATE:

Я предполагаю, что я не совсем ответ на ваш вопрос, я просто дал вам совет о том, как улучшить свой код. На этот раз я постараюсь ответить на ваш вопрос:

Цикл $digest - это этап, на котором Угловой обеспечивает изменение настроек модели, , чтобы он мог визуализировать представление с обновленными изменениями.Для этого Угловой запустит цикл, в котором каждая итерация вычисляет все выражения шаблона вида, а также функции $watcher$scope. Если в текущей итерации результат будет таким же, как и предыдущий, , тогда Angular выйдет из цикла. В противном случае он повторит попытку. Если после 10 попыток все еще не улажено, Angular выйдет с ошибкой: "Infite $digest Loop Error" (infdig).

Именно поэтому в первый раз, когда цикл $digest выполняется, все выражения оцениваются (по крайней мере) дважды. И затем каждый раз, когда вы вносите изменения в $scope или запускаете один из $watcher s $scope, цикл $digest будет запускаться снова, чтобы убедиться, что все улажено, поэтому ваши выражения будут снова оценены. Вот как Угловая делает «привязку данных», это нормальное поведение.

Так что в вашем случае, когда в шаблоне вы делаете это: {{formatMyDate(date)}} или это {{date | formatMyDate}} вы определяете угловые выражения, которые будут оцениваться каждый раз, когда $digest цикл запускается, который, как вы можете себе представить, очень часто. Вот почему очень важно убедиться, что $filters (или функции), которые вы используете в своем представлении, являются эффективными и безгосударственными.

+0

Будет ли фильтр вызываться несколько раз, пока значение «стабилизируется»? – Leonardo

+1

@ Leonardo yep, в AngularJs есть привязка данных, а это означает, что когда модель меняет представление, оно обновляется, так как ваша «дата» определена в области $, цикл $ diggest будет обнаруживать изменения и обновлять представление. – Josep

+0

Так что в основном это было бы точно так же, как с моим решением, так и с вашим? Это будет только вопрос чистого кода и хорошей практики, но, в конце концов, фильтр или мой 'formatMyDate' будут вызываться несколько раз, не так ли? – Leonardo

1

Вы c a сделайте так:

{{date && formatMyDate(date)}} 

выполнит только второй случай, если первое условие существует и отличается от нуля и неопределенным.

Проверить эту скрипку: http://jsfiddle.net/HB7LU/7512/