Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disabling submit button based on fields added with ng-bind-html

JSFiddle here: http://jsfiddle.net/c6tzj6Lf/4/

I am dynamically creating forms and buttons and want to disable the buttons if the required form inputs are not completed.

HTML:

<div ng-app="choicesApp">
  <ng-form name="choicesForm" ng-controller="ChoicesCtrl">
    <div ng-bind-html="trustCustom()"></div>
    <button ng-repeat="button in buttons" ng-disabled="choicesForm.$invalid">
      {{button.text}}
    </button>
  </ng-form> 
</div> 

JavaScript:

angular.module('choicesApp', ['ngSanitize'])
  .controller('ChoicesCtrl', ['$scope', '$sce', function($scope, $sce) {
    $scope.custom = "Required Input: <input required type='text'>";
    $scope.trustCustom = function() {
      return $sce.trustAsHtml($scope.custom);
    };
    $scope.buttons = [
      {text:'Submit 1'},
      {text:'Submit 2'}];
}]);

choicesForm.$invalid is false and does not change when entering text into the input field.

Solution:

I ended up using the angular-bind-html-compile directive from here: https://github.com/incuna/angular-bind-html-compile

Here is the relevant bit of working code:

<ng-form name="choicesForm">
  <div ng-if="choices" bind-html-compile="choices"></div>
  <button ng-click="submitForm()" ng-disabled="choicesForm.$invalid">
    Submit 
  </button>
</ng-form>

And choices might be a snippit of HTML like this:

<div><strong>What is your sex?</strong></div>
<div>
  <input type="radio" name="gender" ng-model="gender" value="female" required>
  <label for="female"> Female</label><br>
  <input type="radio" name="gender" ng-model="gender" value="male" required>
  <label for="male"> Male</label>
</div>
like image 693
disperse Avatar asked Mar 10 '16 15:03

disperse


People also ask

How do I disable the button until input fields have values?

Just click f12 in your browser, find the submit button in the html, and then remove the disabled ! It will submit the form even if the inputs are empty.

How do I make my submit button disabled?

1.1 To disable a submit button, you just need to add a disabled attribute to the submit button. $("#btnSubmit"). attr("disabled", true); 1.2 To enable a disabled button, set the disabled attribute to false, or remove the disabled attribute.

How would you ensure that the button code will disable the submit button if the form is invalid?

If the textbox control value is invalid, we also want to disable the submit button so that the user cannot submit the form. We are using the “ng-disabled” property for the control to do this based on the conditional value of the “$dirty” and “$invalid” property of the control.

How do you disable submit button until form is filled in JS?

document. getElementById('submitbutton'). disabled = !


3 Answers

The main problem is that ngBindHtml doesn't compile the html - it inserts the html as it is. You can even inspect the dynamic input and see that it doesn't have the ngModel's CSS classes (ng-pristine, ng-untouched, etc) which is a major red flag.

In your case, the form simply doesn't know that you've added another input or anything has changed for that matter. Its state ($pristine, $valid, etc) isn't determined by its HTML but by the registered NgModelControllers. These controllers are added automatically when an ngModel is linked.

  • For example this <input required type='text'> won't affect the form's validity, even if it's required, since it doesn't have ngModel assigned to it.
  • But this <div ng-model="myDiv" required></div> will affect it since it's required and has ngModel assigned to it.

The ngDisabled directive on your buttons works as expected since it depends on the form's $invalid property.

See this fiddle which showcases how ngModel registers its controller. Note that the html containing the dynamic input gets compiled after 750ms just to show how NgModelControllers can be added after FormController has been instantiated.

There are a few solutions in your case:

  • use a custom directive to bind and compile html - like this one

  • use ngInclude which does compile the html

  • use $compile to compile the newly added HTML but this is a bit tricky as you won't know exactly when to perform this action

like image 148
Cosmin Ababei Avatar answered Sep 30 '22 16:09

Cosmin Ababei


This is an answer yet imcomplete because i cannot do the code at the moment.

I think your html will be included, not compiled. So the inputs are not bind to angular and are not part of the angular form object.

The only way i see is to use a directive that will compile the passed html and add it to your form. This may be quite tricky though, if you want to go on this way i suggest to edit your question to ask for the said directive.

However i'm not really familiar with $compile so i don't know if it'll work to just add $compile around $sce.trustAsHtml()

like image 30
Walfrat Avatar answered Sep 30 '22 18:09

Walfrat


You can write a method as ng-disabled does not work with booleans, it works with 'checked' string instead:

So on your controller place a method :

$scope.buttonDisabled = function(invalid){
        return invalid ? "checked" : "";
    };

And on your view use it on angular expression :

<button ng-repeat="button in buttons" ng-disabled="buttonDisabled(choicesForm.$invalid)">

Here is a working fiddle

like image 37
Rosmarine Popcorn Avatar answered Sep 30 '22 16:09

Rosmarine Popcorn