The following template, shown below controller snippet, is persistently disabling the submit button in AngularJS. I have tried to use $scope.$apply();
on the last line of $scope.getTextValueAndValidate
function but when that line executes my form loses all entries (clears entirely).
How do I resolve this to make my button enabled and prevent clearing the form fields after all entries are valid?
Controller Snippet ($scope.valid checks if form fields not shown are filled out)
angular.module('Risk').controller('CreateRiskController', ['$http', '$resource', '$scope', '$state', '$window', '$timeout', '$interval', '$sce', 'CommonService', function($http, $resource, $scope, $state, $window, $timeout, $interval, $sce, CommonService){
$scope.flags = {
disabled: true
}
$scope.valid = function(){
return($scope.risk.risktitle.trim() != '' &&
$scope.risk.riskstatement.trim() != '' &&
$scope.risk.context.trim() != '' &&
$scope.risk.closurecriteria.trim() != '' &&
$scope.risk.likelihood.trim() != '' &&
$scope.risk.technical.trim() != '' &&
$scope.risk.technical.trim() != '' &&
$scope.risk.cost.trim() != '' &&
!isNaN($scope.risk.likelihood) && Number($scope.risk.likelihood) >= 1 && Number($scope.risk.likelihood) <= 5 &&
!isNaN($scope.risk.technical) && Number($scope.risk.technical) >= 1 && Number($scope.risk.technical) <= 5 &&
!isNaN($scope.risk.schedule) && Number($scope.risk.schedule) >= 1 && Number($scope.risk.schedule) <= 5 &&
!isNaN($scope.risk.cost) && Number($scope.risk.cost) >= 1 && Number($scope.risk.cost) <= 5);
}
$scope.getTextValueAndValidate = function(obj, model, field){
$scope.clearValidation(field);
CommonService.getTextValue(obj, model, 'risk', field);
$scope.validate(obj, field);
valid = $scope.valid();
$scope.flags.disabled = !valid;
}
}]);
Template
<div id="formcontainer" ng-app="Risk" ng-controller="CreateRiskController" ng-init="init()">
<div id="mycreateform" class="container" type="space" layout-padding="" ng-cloak="">
<init-risk />
<form webix-ui="config" id="form" name="CreateRisk" role="form" ng-submit="valid() && submit()" novalidate>
<table id="details" class="layout" border="1">
<tr>
<td class="label">
Title
</td>
<td class="locked">
<div webix-ui="risktitleConfig" id="risktitle" name="risktitle" />
</td>
</tr>
<tr>
<td class="label">
Risk Statement
</td>
<td class="locked">
<div webix-ui="riskstatementConfig" id="riskstatement" name="riskstatement" />
</td>
</tr>
<tr>
<td class="label">
Context
</td>
<td class="locked">
<div webix-ui="contextConfig" id="context" name="context" />
</td>
</tr>
<tr>
<td class="label">
Closure Criteria
</td>
<td class="locked">
<div webix-ui="closurecriteriaConfig" id="closurecriteria" name="closurecriteria" />
</td>
</tr>
<!--tr class="text">
<td class="label">
Category
</td>
<td class="locked">
<div id="category" name="category" />
</td>
</tr-->
</table>
<h2>Initial Risk Assessment</h2>
<div class="nested">
<div class="info">
<table id="details" border="1">
<tr>
<td class="label">
Likelihood
</td>
<td class="locked">
<div webix-ui="likelihoodConfig" id="likelihood" name="likelihood" />
</td>
</tr>
<tr>
<td class="label" colspan="2">
Consequence
</td>
</tr>
<tr>
<td class="label margin-left">
Technical
</td>
<td class="locked">
<div webix-ui="technicalConfig" id="technical" name="technical" />
</td>
</tr>
<tr>
<td class="label margin-left">
Schedule
</td>
<td class="locked">
<div webix-ui="scheduleConfig" id="schedule" name="schedule" />
</td>
</tr>
<tr>
<td class="label margin-left">
Cost
</td>
<td class="locked">
<div webix-ui="costConfig" id="cost" name="cost" />
</td>
</tr>
</table>
<button type="submit" ng-disabled="flags.disabled" class="raised primary">Create Risk</button>
</form>
</div>
</div>
Directive (inner relevant portion shown)
function getLevelConfig(attr)
{
var config =
{
view:"text",
value: scope.risk[attr],
on: {
"onChange": function(){var obj = this.eventSource || this; scope.getTextValueAndValidate(obj, scope, attr); assignRiskLevel();}
},
attributes: {
maxlength: 1
},
responsive: true,
width: "36",
height: "30",
required: true
};
return config;
}
function getTextConfig(attr)
{
var config =
{
view:"text",
value: scope.risk[attr],
on: {
"onChange": function(){ var obj = this.eventSource || this; scope.getTextValueAndValidate(obj, scope, attr)}
},
responsive: true,
width: "520",
height: "30",
validate: webix.rules.isNotEmpty,
required: true
};
return config;
}
function getTextareaConfig(attr)
{
var config =
{
view:"textarea",
value: scope.risk[attr],
on: {
"onChange": function(){var obj = this.eventSource || this; scope.getTextValueAndValidate(obj, scope, attr)},
//"onBlur": function(){scope.validate(scope.actionitem.actionitemstatement, 'actionitemstatement')}
},
responsive: true,
width: "520",
height: "97",
validate: webix.rules.isSelected,
required: true
};
return config;
}
function getSelectConfig(attr, options)
{
var config =
{
view: "richselect",
value: scope.risk[attr],
options: options,
on: {
//"onChange": function(){var obj = this.eventSource || this; getValue(obj, 'assignor')},
"onChange": function(){var obj = this.eventSource || this; scope.getItemValueAndValidate(obj, scope, attr)}
//"onBlur": function(){scope.validate(scope.actionitem.assingor, 'assignor')}
},
responsive: true,
width: "520",
height: "30",
validate: webix.rules.isSelected,
required: true
};
return config;
}
scope.risktitleConfig = getTextConfig('risktitle');
scope.riskstatementConfig = getTextareaConfig('riskstatement');
scope.contextConfig = getTextareaConfig('context');
scope.closurecriteriaConfig = getTextareaConfig('closurecriteria');
scope.categoryConfig = getSelectConfig('category');
scope.likelihoodConfig = getLevelConfig('likelihood');
scope.technicalConfig = getLevelConfig('technical');
scope.scheduleConfig = getLevelConfig('schedule');
scope.costConfig = getLevelConfig('cost');
I found a helpful solution to my problem that worked, despite not directly using an angular directive.
How to set ng-disabled inside directive
Modifying my solution was straightforward with the suggestion.
I manipulated the DOM in side my own directive instead of using AngularJS's ng-disabled directive.
if (scope.valid())
(document.querySelector('#submit')).removeAttribute('disabled');
else
(document.querySelector('#submit')).setAttribute('disabled', 'disabled');
I then added an id to my button an a disabled attribute initialized to disabled in my template.
<button id="submit" type="submit" disabled="disabled" class="raised primary">Create Risk</button>