I'm trying to figure out the "preferred" or "angular-way" of sharing properties or state between controllers/directives. There are several methods to implement this, but I want to keep with best-practice. Below are some banal examples of how this can be implemented:
1. Using $scope.$watch
// The parent controller/scope
angular.module('myModule').controller('parentController', ['$scope', function($scope) {
    $scope.state = {
        myProperty: 'someState'; // Default value to be changed by some DOM element
    };
}]);
// The child controller/scope.
angular.module('myModule').controller('childController', ['$scope', function($scope) {
    $scope.$watch('state.myProperty', function (newVal) {
        // Do some action here on state change
    });
}]);
Edit: Based on answers below, this is bad practice and should be avoided. It is untestable and places an unwanted DOM dependancy.
2. Using $broadcast
// The parent controller
angular.module('myModule').controller('parentController', ['$scope', function($scope) {
    var myProperty = 'someState';
    $scope.setState = function (state) {
        myProperty = state; // Set by some other controller action or DOM interaction.
        $scope.$broadcast('stateChanged', state); // Communicate changes to child controller
    }
}]);
// The child controller.
angular.module('myModule').controller('childController', ['$scope', function($scope) {
    $scope.$on('stateChanged', function (evt, state) {
        // Do some action here
    }
}]);
Edit: Equally bad practice as you need to know the placement of the controllers in the DOM in order to determine weather to use $broadcast (down the DOM) or $emit (up the DOM).
3. Using service
angular.module('myModule').factory('stateContainer', [function () {
    var state = {
            myProperty: 'defaultState'
        },
        listeners = [];
    return {
        setState: function (newState) {
            state.myProperty = newState;
            angular.forEach(listeners, function (listener) {
                listener(newState);
            });
        },
        addListener: function (listener) {
            listeners.push(listener);
        }
    }
}]);
// The parent controller
angular.module('myModule').controller('parentController', ['$scope', 'stateContainer', function($scope, stateContainer) {
    $scope.setState = function (state) {
        stateContainer.setState(state);
    };
}]);
// The child controller.
angular.module('myModule').controller('childController', ['$scope', 'stateContainer', function($scope, stateContainer) {
    stateContainer.addListener(function (newState) {
        // Do some action here
    });
}]);
There are probably some approaches I've missed here, but you get the idea. I'm trying to find the best approach. Although verbose, I personally lean towards #3 in the list here. But I come from a Java and jQuery background where listeners are widely used.
Edit: Answers below are insightful. One talks of sharing state between parent/child directives using the require directive configuration. The other talks of sharing service or service properties directly to the scope. I believe that depending on the need, they are both right in what is or is not best practice in Angular. 
 
     
     
     
    