Q: require ngModel syntax in AngularJS I see the following:
// my-directive.js    
return {
  require: 'ngModel',
  scope: {
    ngModel: '=',
  },
  controller: controller,
  link: myLink
};

// my-link.js
return function(scope, $element, attrs, modelController) {
  scope.onMyClick = function(event) {
    modelController.$setViewValue(getItem(event));
  }
};

// foo.html
<my-directive ng-model="myModel"></my-directive>

Is the ng-model directive used to provide a two way data-binding to the myModel in the outer scope where the my-directive instance is declared?
Is this the idiomatic way to provide two-way data binding between a directive and an outer model in Angular 1.4?
Does the require: 'ngModel' in the directive definition do anything other than inject the controller instance for the ng-model directive instance into the link function my-link? 
Finally, does it make the controller of ng-model available on the scope for the controller of my-directive to use?

A: There are 2 different things here - ng-model as directive and ngModel: '=' in directive as attribute. Lets split them:
<my-directive ng-model="myModel" whatever="myModel"></my-directive>

return {
  require: 'ngModel',
  scope: {
    myModel: '=',
  },
  controller: controller,
  link: myLink
};


Is the ng-model directive used to provide a two way data-binding to
  the myModel in the outer scope where the my-directive instance is
  declared?

No, 2-way binding is provided by definition inside directive. (whatever here)

Is this the idiomatic way to provide two-way data binding between a
  directive and an outer model in Angular 1.4?

One you used scope : { whatever : '='} is usual way.

Does the require: 'ngModel' in the directive definition do anything
  other than inject the controller instance for the ng-model directive
  instance into the link function my-link

Not that much, if u use directive without ngModel it will throw error.

Finally, does it make the controller of ng-model available on the
  scope for the controller of my-directive to use?

No, it doesnt add anything to your scope. You just can access injected controller.
