Это лучше делать немного по-другому - вместо того, чтобы слушать изменения scope, лучше привязаться к событию инпута и исходить уже из этого. Еще одним преимуществом привязки именно к события является то, что ты можешь отменить изменение до того, как произойдет рендер. В случае наблюдения за значением в scope ты в любом случа сделаешь 2 рендера инпута: сначала отрисуешь с недопустимым символом, а затем заменишь значение на допустимое(в примере на доли секунды появляется невалидное значение, а затем снова исчезает).
Насчёт таймаута - это один из способов применить апдейты к view части. Чтобы ангуляр отрисовал новое значение, ему нужно совершить digest цикл - то есть пройти по значениям и сравнить их. $timeout - один из безопасных способов это сделать, так как после отработки он запускает digest цикл.
Вот пример того, как это можно сделать.В твоём примере директива не нужна - ты просто делаешь watch из котроллера и меняешь значение, если нужно.