Angular: Transclude

http://angularjs.org/

by miphe

HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<div class="page" ng-app="myApp" ng-controller="MyAppCtrl">
    <form ng-controller="MyFormCtrl">
        <div class="form-group">
            <in></in>
            <p class="help-block">Write anything in the textarea, the result below should update.</p>
        </div>
        <button type="button" class="btn btn-primary" ng-click="resetModel()">
            Reset model to ---
        </button>
    </form>
    <hr />
    <h3>Result:</h3>
    <p id="result">-</p>
</div>

CSS

.page { padding: 3em; }
#result { background-color: #fdfeef; padding: 2em; border: 1px solid #ffeeaa; font-family: monospace; }

JavaScript

var myAppC = angular.module('myApp',['myApp.ctrl', 'myApp.directives']);
var myAppC = angular.module('myApp.ctrl',[]);
var myAppD = angular.module('myApp.directives',[]);

// Insignificant controller
angular.module('myApp.ctrl')
    .controller('MyAppCtrl', function($scope) {
        console.log('MyAppCtrl Scope: ', $scope.$id);
    });

// Controller that handles our model 'target'
angular.module('myApp.ctrl')
    .controller('MyFormCtrl', function($scope) {
        console.log('MyFormCtrl Scope: ', $scope.$id);
        
        // Resets the model to '---'
        $scope.resetModel = function() {
            $scope.target = '---';
        };
    
        // Applies a watcher to the model
        $scope.$watch('target', function(n, o) {
            $scope.reflectModel(n);
        });
    });

// Textarea directive called <in>
angular.module('myApp.directives')
    .directive('in', function() {
        return {
            restrict: 'E',
            template: '<textarea rows="3" class="form-control" ng-model="target"></textarea>',
            transclude: true,
            link: function(scope, element, attrs, ctrl, transclude) {
                // transclude(scope, function(clone, scope) {
                transclude(scope.$parent, function(clone, scope) {
                    console.log('Transcluded Scope', scope.$id, ' (same as MyAppCtrl)');
                    
                    // Updates the DOM with new value
                    scope.reflectModel = function(n) {
                        $('#result').text(n);
                    };
                });
            }
        };
    });