0

Trying to find the best practices with AngularJS. Here's the deal:

There are two different pages with forms where each of them have their own form fields. But there is a one common functionality on both of the forms: they have an autocomplete field which the user can use to select multiple email addresses that exist in the system.

The selected email addresses are stored to the model/scope so that they can be shown on the HTML page. Here's an example:

<div ng-controller="MyCtrl">
    <form ng-submit="selectCurrentEmail()" novalidate>
        <input type="text" 
               class="form-control"
               ng-model="responsiblePerson" />
        <input type="submit" value="Add" />

        <div ng-repeat="email in formData.selectedEmails">
            <div>
                {{email}} <a href="" ng-click="removeEmail(email)">x</a>
            </div>
        </div>
    </form>
</div>

and the angularjs part:

var myApp = angular.module('myApp', []);

function MyCtrl($scope) {
    $scope.formData = {selectedEmails: []};

    $scope.selectEmail = function(email) {
        if (email != null && $.inArray(email, $scope.formData.selectedEmails) == -1) {
            $scope.formData.selectedEmails.push(email);
            $scope.responsiblePerson = null;
        }   
    };

    $scope.removeEmail = function(email) {
        var index = $.inArray(email, $scope.formData.selectedEmails);

        if (index != -1) {
            $scope.formData.selectedEmails.splice(index, 1);
        }
    };

    $scope.selectCurrentEmail = function() {
        $scope.selectEmail($scope.responsiblePerson);
    };
}

http://jsfiddle.net/PqpYj/

(doesn't contain the autocomplete since it's not the main issue here..)

This all works fine, but I don't want to repeat the same logic in both of the controllers. What I would like to have is a service or a base controller that can take care of setting and removing the selected email addresses. And when the user is done, the scope would have just the selected email addresses.

So, do you think there's a good way to generalize the three functions in the scope? Any ideas making this better?

3
  • 1
    As you suggested, write a directive module for your autocomplete field, which saves to an angular service Commented Oct 28, 2013 at 7:21
  • possible duplicate of Can one controller call another in AngularJS? Commented Oct 28, 2013 at 7:26
  • Using services is the better option here Commented Oct 28, 2013 at 8:20

1 Answer 1

1

Because this is a UI element, I would put the logic into a Directive.

myApp.directive('mailSelector', function() {
    return {
        scope: {
            emails: '='
        },
        template: '<form ng-submit="selectCurrentEmail()" novalidate>' +
        '<input type="text"'+ 
        '       class="form-control"'+
        '       ng-model="responsiblePerson" />'+
        '<input type="submit" value="Add" ng-click="selectCurrentEmail()" />'+

        '<div ng-repeat="email in emails">'+
        '    <div>' +
        '        {{email}} <a href="" ng-click="removeEmail(email)">x</a>' +
        '    </div>' +
        '</div>' +
    '</form>',        
        link: function($scope, $element, $attrs) {
            $scope.selectCurrentEmail = function() {
                $scope.selectEmail($scope.responsiblePerson);
            }

            $scope.selectEmail = function(email) {
                if (email != null && $.inArray(email, $scope.emails) == -1) {
                    $scope.emails.push(email);
                    $scope.responsiblePerson = null;
                }
            }

            $scope.removeEmail = function(email) {
                var index = $.inArray(email, $scope.emails);
                if (index != -1) {
                    $scope.emails.splice(index, 1);
                }
            };
        }
    };
});

Controllers can retrieve a list of emails from Directive via emails parameter defined with the directive.

I have created a JSFiddle here.

To share previously input email addresses for auto-completion, I would modify the directive to use a Service, which holds the list of previously input email addresses.

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

1 Comment

Thanks, this is exactly what I was looking for! Still learning all the good stuff in AngularJS. I guess I didn't realize you could just access the scope right in the link function like that.. :)

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.