2

I'm building a form builder AngularJS app, and I have the following AngularJS directive representing the UI to edit a TextField:

angular.module('myApp.directives').directive('textFormFieldElement', ['$timeout', function($timeout) {
    'use strict';

    return {
        restrict: 'A',
        scope: {
            element: '='
        },
        template: '<div class="form-element text-form-field">' +
                  '    <span class="identifier">TF</span>' +
                  '    <strong class="heading" ng-bind="headingText()"></strong>' +
                  '    <div class="editor">' +
                  '        <div class="form-group">' +
                  '            <label>Enter the field name:</label>' +
                  '            <input ng-model="element.fieldName" type="text" class="form-control" />' +
                  '        </div>' +
                  '        <div class="form-group">' +
                  '            <label>Enter a label for the field:</label>' +
                  '            <input ng-model="element.label" type="text" class="form-control" />' +
                  '        </div>' +
                  '        <div class="form-group">' +
                  '            <label>Enter a note for the field:</label>' +
                  '            <input ng-model="element.note" type="text" class="form-control" />' +
                  '        </div>' +
                  '        <div class="checkbox">' +
                  '            <label>' +
                  '                <input ng-model="element.required" type="checkbox" /> Required' +
                  '            </label>' +
                  '        </div>' +
                  '    </div>' +
                  '</div>',

        link: function(scope, element, attributes) {
            scope.element.fieldName = scope.element.fieldName || 'TextField';

            // Expand the editor when creating new elements, and focus on the first field once rendered.
            if (!scope.element._id) {
                $timeout(function() {
                    element.find('.editor').addClass('expanded');
                    element.find('.editor').find('input:first').select();
                }, 10);
            }

            scope.headingText = function() {
                if (scope.element.fieldName.length && scope.element.fieldName.length > 0) {
                    return scope.element.fieldName;
                }

                return 'TextField';
            };
        }
    };
}]);

I also have other controls, like a PhoneField, an EmailField, and a RadioButtonListField.

These directives will often have common HTML in their templates as well as common JavaScript behavior. I'd like a way to share this across directives, without polluting the global namespace.

What are some ways this can be achieved?

4
  • 1
    Templates can be also passed in with templateUrl, meaning that one template an be used any amount of times, services seem like a good choice for sharing javascript code. Commented Mar 18, 2014 at 18:01
  • True, but would I need to reuse the same template across directives? The key is that each template may have slight variations. Commented Mar 18, 2014 at 18:22
  • I'm curious if you've come up with an elegant solution to this problem. I have very similar needs. Commented Apr 23, 2016 at 15:11
  • Well, the need hasn't arisen often, honestly. The only way I have found to share HTML is to use Browserify with the plugins like stringify and require-globify that lets you pull in HTML using require(). As for sharing common JavaScript functionality, I would suggest looking at using services. I would be careful to not name the services too generally and cram too much into one service. I would also be careful about sharing data between services, as services are only initialized once per app load. Commented Apr 24, 2016 at 22:08

1 Answer 1

1

For template sharing you could extract common template code into 'template directives', i.e. directives that only define template without behavior. This way you can re-use these template directives inside the templates of other directives.

For sharing common JavaScript behavior the two recommended ways are either via Angular services (service/factory) or in the case of directives using directive controller.

For the latter, see the Creating Directives that Communicate section at http://docs.angularjs.org/guide/directive on how to implement this.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.