2

I am working on an app with custom form controls which need to be validated before clicking a Next button. For standard HTML form controls, angular's built-in validation is quite nice, allowing me to bind my Next button with a ng-disabled on the form.$valid value. However, I am having trouble getting custom validation working in a rather difficult control. Here is my situation:

  • I have a custom directive for my form control (a component called mySlider)
  • mySlider wraps a 3rd-party component angular-slider -- yes, I know it's deprecated
  • We want to validate that the user has clicked the slider. The Next button should not be enabled if the user has not clicked the slider control.
  • I tried to create this custom validation by adding a has-changed attribute to the 3rd party directive element, and updating it on-click, however it does not seem to be working as expected.
  • I tried to examine how the built-in validations work (ex: try searching for var requiredDirective), as well as reading the Angular Forms Guide but it's still a little unclear
  • We have a requirement to not use jQuery, jQuery UI/Mobile etc, however it must also work for mobile touch events

See my Plunk and help - please fork if you're going to edit. The custom validator and custom Slider directive is in script.js while the 3rd-party directive is in angular-slider.js.

1
  • I'll have something for you shortly Commented Sep 24, 2015 at 4:47

1 Answer 1

1

You need to use the $setValidity function on your form model to toggle the validity state of the slider. This will give you the flexibility you desire to make complicated form rules which each component being different.

Here is working code to solve your problem. I converted your ng-change to an ng-click that compared begin and after values Working Plunkr

link: function (scope, element, attrs) {
    // Slider init
    scope.max = 100;
    scope.min = 0;
    scope.initial = 50;
    scope.sliderValue = scope.initial;
    //Set validity to false by default
    scope.myForm.mySliderControl.$setValidity('hasChanged',false); 

    // ng-change is not coded with this example, converted to ng-click
    scope.change = function(){
      if(scope.initial != scope.sliderValue){
          console.log("I have changed!");
          scope.myForm.mySliderControl.$setValidity('hasChanged',true);
      } 
    };
  }

On a side note. Several issues that compounded to cause your problem:

  1. angular-slider is not coded to enable the ng-change functionality you were attempting to use
  2. Your mySlider directive should have an isolate scope and pass options via a config object. Currently, it is on the same scope as the controller which means the directive can't really be reused.
  3. Compounding directive here only adds complications
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for the post--that's helpful. One drawback to this approach, though, is that I couldn't just add my-slider to myOtherForm. Is there a way to make the reference to myForm somehow more generic?
I think I know what to do... I could pass in the form name to the mySlider directive, then dynamically refer to the form with scope[formName][mySliderName].$setValidity. Let's see if it works...
When I make custom directives like the one you are talking about, I typically have an options attribute which is linked a scope object which passes in my configurations settings <my-slider options="slider1Options"></my-slider> and $scope.slider1Options. From there I can set-up two way data binding (pass in scope.myForm.mySliderControl as a property on the object).
I may be going about this the wrong way, but I'm still unable to dynamically use this technique. See Updated Plunk I wasn't able to call the $setValidity using the bracket approach.
I got it!!! For whichever reason, passing in the myForm object in a different attribute worked. See same plunk as in last comment. Thanks for your help!
|

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.