AngularJS / Webix 表单 - 设置 ng-disabled 值后无法启用按钮?
AngularJS / Webix Form - Can't enable button after setting ng-disabled value?
控制器代码段下方显示的以下模板持续禁用 AngularJS 中的提交按钮。我曾尝试在 $scope.getTextValueAndValidate
函数的最后一行使用 $scope.$apply();
,但是当该行执行时,我的表单会丢失所有条目(完全清除)。
如何解决此问题以启用我的按钮并防止在所有条目均有效后清除表单字段?
控制器代码段($scope.valid 检查是否填写了未显示的表单字段)
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;
}
}]);
模板
<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>
指令(显示内部相关部分)
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');
尽管没有直接使用 angular 指令,但我找到了一个有用的解决方案来解决我的问题。
How to set ng-disabled inside directive
根据建议修改我的解决方案很简单。
我在自己的指令中操纵了 DOM,而不是使用 AngularJS 的 ng-disabled 指令。
if (scope.valid())
(document.querySelector('#submit')).removeAttribute('disabled');
else
(document.querySelector('#submit')).setAttribute('disabled', 'disabled');
然后我在我的按钮中添加了一个 id 和一个在我的模板中初始化为 disabled 的 disabled 属性。
<button id="submit" type="submit" disabled="disabled" class="raised primary">Create Risk</button>
控制器代码段下方显示的以下模板持续禁用 AngularJS 中的提交按钮。我曾尝试在 $scope.getTextValueAndValidate
函数的最后一行使用 $scope.$apply();
,但是当该行执行时,我的表单会丢失所有条目(完全清除)。
如何解决此问题以启用我的按钮并防止在所有条目均有效后清除表单字段?
控制器代码段($scope.valid 检查是否填写了未显示的表单字段)
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;
}
}]);
模板
<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>
指令(显示内部相关部分)
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');
尽管没有直接使用 angular 指令,但我找到了一个有用的解决方案来解决我的问题。
How to set ng-disabled inside directive
根据建议修改我的解决方案很简单。
我在自己的指令中操纵了 DOM,而不是使用 AngularJS 的 ng-disabled 指令。
if (scope.valid())
(document.querySelector('#submit')).removeAttribute('disabled');
else
(document.querySelector('#submit')).setAttribute('disabled', 'disabled');
然后我在我的按钮中添加了一个 id 和一个在我的模板中初始化为 disabled 的 disabled 属性。
<button id="submit" type="submit" disabled="disabled" class="raised primary">Create Risk</button>