Update:

The $onChanges() lifecycle hook has been backported from 2 as of Angular 1.5.3. $onChanges() will fire on any change to one-way ('<') or interpolation ('@') bindings, which essentially takes care of exactly this case.

Past Update:

I was wrong. $onInit doesn't wait for the bindings to get stabilized.

I find this to be one of the most accurate $onInit definition:

$onInit lifecycle hook: Introducing a new lifecycle hook for directive controllers, called after all required controllers have been constructed. This enables access to required controllers from a directive's controller, without having to rely on the linking function.

In the documentation of $compile there are some instances where the words "bindings" and "initialized" are used together. In this context, it simply means that all of the directive's bindings have had their watchers set up.

To answer this question, as Angular 1.5.0, there isn't any way to wait for the directive's bindings to get stabilized without using a watcher. This isn't a bad thing as you'll have greater control while defining your watchers. The following example showcases how a directive may wait for its bindings to get stabilized: