2

I'm trying to figure out if it is possible to validate data client side to ensure that no duplicates are sent to the database. I have an angular app which gets data from an api call. This is my current controller for adding a new subject (functioning perfectly, but without data validation):

angular.module('myApp.controllers')
    .controller('SubjectNewCtrl', ['$scope', 'SubjectsFactory', '$location', '$route',
    function ($scope, SubjectsFactory, $location, $route) {

        // callback for ng-click 'createNewSubject':
        $scope.createNewSubject = function () {
            SubjectsFactory.create($scope.subjects);
            $location.path('/subjects');

        }

    }]);

And here is what I have been attempting for data validation:

angular.module('myApp.controllers')
    .controller('SubjectNewCtrl', ['$scope', 'SubjectsFactory', '$location', '$route',
    function ($scope, SubjectsFactory, $location, $route) {

        // callback for ng-click 'createNewUser':
        $scope.createNewSubject = function () {

            var newSubject = $scope.subject.name;
            var someSubject = $scope.subjects;
            var oldSubject;

            if(newSubject){
                angular.forEach($scope.subjects, function(allSubjects){
                    if(newSubject.toLowerCase() == allSubjects.name.toLowerCase()){
                        oldSubject = true;
                    }
                });
                if (!oldSubject){
                   SubjectsFactory.create($scope.subjects); 
                }
            }
        }

    }]);

This gives me a console error- TypeError: Cannot read property 'name' of undefined. How do I access the 'name' property of my new subject from the html? Can anyone tell me if what I am trying to do is possible/ makes sense?

2
  • Can you share a plunker? It's hard to understand how this is all hooked up. The error means "$scope.subject is undefined", is $scope.subject the subject to be added? Commented Mar 5, 2014 at 16:44
  • Yes, it is the object to be added. I don't know if that makes sense. I will try get a plunker working. Commented Mar 5, 2014 at 16:51

2 Answers 2

2

If I understand your question correctly, you should use a directive for the specific field you are trying to validate. A unique email directive would be a common example. Here is one I have used in the past. Nothing fancy.

MyApp.directive('uniqueEmail', ['$http', function($http) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, ctrl) {
            //set the initial value as soon as the input comes into focus
            element.on('focus', function() {
                if (!scope.initialValue) {
                    scope.initialValue = ctrl.$viewValue;
                }
            });
            element.on('blur', function() {
                if (ctrl.$viewValue != scope.initialValue) {
                    var dataUrl = attrs.url + "?email=" + ctrl.$viewValue;
                    //you could also inject and use your 'Factory' to make call
                    $http.get(dataUrl).success(function(data) {
                        ctrl.$setValidity('isunique', data.result);
                    }).error(function(data, status) {
                        //handle server error
                    });
                }
            });
        }
    };
}]);

Then in your markup you could use it like so.

<input type="text" name="email" ng-model="item.email" data-unique-email="" data-url="/api/check-unique-email" />
<span class="validation-error" ng-show="form.email.$error.isunique && form.email.$dirty">Duplicate Email</span>

Hope this is what you were looking for.

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

2 Comments

Thanks, this looks like what I need to do. How would I inject my factory service?
MyApp.directive('uniqueEmail', ['myFactory', function(myFactory){ ...etc.
-1

I have implemented object creation in Angular js many times.

My createNew button method typically just created a new javascript Object() and set the scope.currentObject to the new Object();

In your case it appears that $scope.subject is not initialized to anything, hence the error.

I guess that there must be a html input on your form that is bound the subject.name field but without a subject Object to hold the name it is effectively unbound.

If I wanted users to enter a name then click create button to validate that the name is not used. I would bind the new Name input to a different $scope variable (perhaps $scope.newName)

Then in the createNewSubject method you can actually create a new subject like this:

  $scope.subject = new Object();
  $scope.subject.name = $scope.newName;

Then you can run your validation code.

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.