AngularJS > = 1.3: ng-if с однократной привязкой, которая удаляется, когда выражение принимает значение true

#angularjs

#angularjs

Вопрос:

Я активно использую этот трюк

 ng-if="::vm.isLoaded || undefined"
  

В этом случае, если vm.isLoaded что-то является ложным, наблюдение будет продолжать работать, потому что undefined в этом случае всегда возвращается, и «одноразовая привязка» продолжает наблюдать, пока выражение не получит значение, отличное от undefined .

Есть ли какой-нибудь способ добиться обратного? Т.Е. продолжайте наблюдать за истинными значениями, пока выражение undefined не примет значение, или какое-либо другое «волшебное» значение.

Реальный вариант использования — это загрузка… gif, который после загрузки содержимого должен исчезнуть.

 ng-if="!vm.isLoaded"
  

работает нормально (показывает загружаемый gif при загрузке и скрывает его после загрузки), но как только материал загружен, я хочу, чтобы часы были удалены (материал никогда не станет «выгруженным» снова).

Ответ №1:

Копирование с GitHub:

Отрицательное ngIf значение с однократной привязкой действительно невозможно в настоящее время и является прецедентом (единственным afaik), который позволяет ngUnless (противоположно ngIf ) включить то, что уже невозможно.

Более подробный обходной путь для достижения желаемого — использовать ngSwitch (хотя это добавляет дополнительный элемент DOM, который вы, конечно, можете скрыть).

 <div ng-switch="::(foo || undefined)">
  <div ng-switch-when="undefined">
    This text will be removed for ever,
    once `foo` evaluates to something truthy
  </div>
</div>
  

Тем не менее, ngIf это просто обычная старая директива (и не сложная в этом отношении), поэтому нетрудно скопировать и изменить ее исходный код и включить его в ваше приложение.

Вот демонстрация, похожая на «ngUnless».

Ответ №2:

$watch returns a deregistration function.

Вы можете unregister $watch использовать функцию, возвращаемую $watch вызовом:

 var unwatch = $scope.$watch('isLoaded', function(newValue, oldValue) {
    if(newValue == false || newValue == undefined)
    {
        unwatch();
    }
});
  

Итак, как только ваше isLoaded значение становится false или undefined , watch оно удаляется.

Комментарии:

1. Ну, хорошо, но ваш watch создается (и уничтожается) в коде. Мне все еще нужно иметь выражение для ng-if просмотра в шаблоне. И это часы, которые я пытаюсь уничтожить.

2. возможно, у вас есть выражение ng-if , оно больше не просматривается, как только оно будет уничтожено

3. позвольте мне опубликовать вам пример

4. проверил эту ссылку?

5.В этом примере ваш $watch("count", ... действительно уничтожен, но ng-show он будет продолжать наблюдать after_unwatch вечно. Если вы поместите ::ng-show... это наблюдение, оно будет уничтожено при его оценке true из-за угловой привязки-один раз. Но это не мой вариант использования. Я хочу ng-if удалить что-то из DOM и прекратить просмотр, как только isLoaded он станет правдивым.

Ответ №3:

 ng-hide="::vm.isLoaded || undefined"
  

Это не дает прямого ответа на вопрос, потому что я действительно хотел использовать ng-if для полного удаления загружаемого gif-файла из DOM.

Но скрыть его и удалить watch — следующая лучшая вещь. Я не уверен в относительной проблеме производительности накопления мертвых скрытых элементов DOM по сравнению с накоплением мертвых часов.

Что мне действительно нужно, так это отрицательная версия ng-if . Нравится ng-notif . : P