gpt4 book ai didi

angularjs - 使用 Angular 指令进行复杂表单验证/GUI 操作的优缺点

转载 作者:行者123 更新时间:2023-12-03 08:05:38 25 4
gpt4 key购买 nike

我正在构建一个新的 SPA 前端来替换现有企业的旧系统大杂烩,这些系统已经过时且需要更新。我是 Angular 的新手,想看看社区是否可以给我一些观点。我会陈述我的问题,然后问我的问题。

我必须根据 .js 中的数据生成多个复选框。包括,数据如下:

$scope.fieldMappings.investmentObjectiveMap = [
{'id':"CAPITAL PRESERVATION", 'name':"Capital Preservation"},
{'id':"STABLE", 'name':"Moderate"},
{'id':"BALANCED", 'name':"Moderate Growth"},
// etc
{'id':"NONE", 'name':"None"}
];

复选框是使用 ng-repeat 创建的。 , 像这样:
    <div ng-repeat="investmentObjective in fieldMappings.investmentObjectiveMap">
...
</div>

但是,我需要复选框表示的值映射到不同的模型(不仅仅是 2 路绑定(bind)到 fieldmappings 对象)。为此,我创建了一个指令,它接受目标数组 destarray最终映射到模型。我也知道我需要处理一些非常具体的 gui 控件,例如,如果选中了其他任何内容,则取消选中“无”,或者如果没有选中其他所有内容,则选中“无”。此外,“无”不会是每组复选框中的选项,因此该指令需要足够通用以接受可以摆弄 checked 的验证函数。复选框组的输入状态基于已单击的内容,但如果没有名为 "NONE" 的选项,则足够聪明,不会中断.我开始通过添加一个调用 Controller 中的函数的 ng-click 来做到这一点,但是在查看堆栈溢出时,我读到有人说将 DOM 操作代码放在 Controller 中是不好的——它应该放在指令中。那么我需要另一个指令吗?

至今:
(html):
      <input my-checkbox-group
type="checkbox"
fieldobj="investmentObjective"
ng-click="validationfunc()"
validationfunc="clearOnNone()"
destarray="investor.investmentObjective" />

指令代码:
.directive("myCheckboxGroup", function () {
return {
restrict: "A",
scope: {
destarray: "=", // the source of all the checkbox values
fieldobj: "=", // the array the values came from
validationfunc: "&" // the function to be called for validation (optional)
},
link: function (scope, elem, attrs) {
if (scope.destarray.indexOf(scope.fieldobj.id) !== -1) {
elem[0].checked = true;
}
elem.bind('click', function () {
var index = scope.destarray.indexOf(scope.fieldobj.id);
if (elem[0].checked) {
if (index === -1) {
scope.destarray.push(scope.fieldobj.id);
}
}
else {
if (index !== -1) {
scope.destarray.splice(index, 1);
}
}
});
}
};
})

.js Controller 片段:
.controller( 'SuitabilityCtrl', ['$scope', function ( $scope ) {
$scope.clearOnNone = function() {
// naughty jQuery DOM manipulation code that
// looks at checkboxes and checks/unchecks as needed
};

上面的代码已经完成并且工作正常,除了 clearOnNone() 中的淘气 jquery 代码,这就是我写这个问题的原因。

这是我的问题:在这一切之后,我对自己想——如果我只是用我的 Controller 中编写的 jQuery 手动处理所有这些 GUI 逻辑和验证垃圾,我就可以完成了。写这些复杂的指令,让 future 的开发人员不得不费解更多,如果我只是写了 99% 的人一眼就能理解的 jQuery 代码,在什么时候会变得愚蠢?其他开发人员如何划清界限?

我看到整个堆栈溢出。例如, this question似乎可以用十几行简单的 jQuery 来回答,但他选择了有 Angular 的方式,有一个指令和一个部分......对于一个简单的问题似乎需要做很多工作。

我不希望这个问题违反规则,所以具体来说,我想我想知道:我应该如何编写代码来检查是否选择了“无”(如果它作为这组中的一个选项存在)复选框),然后相应地选中/取消选中其他框?更复杂的指令?我不敢相信我是唯一一个为了满足固执己见的框架而必须实现比所需更复杂的代码的开发人员。我需要使用另一个实用程序库吗?

最佳答案

根据 Jim 的建议,我将其发布在 Programmers.StackExchange.com 上。与此同时,我选择了一种解决方案来处理所有棘手的 DOM 操作。

我尝试了两种方式 - 在 Controller 中处理 DOM 事件,并通过指令处理它:

(通过 Controller ) - .js 代码:

 $scope.clearOnNone = function(groupName, $event) {
var chkboxArr = $('input[name^=' + groupName + ']'),
nonNoneValChecked = false,
targetElem = null,
labelText = "";

// get the target of the click event by looking at the <label> sibling's text
targetElem = event.target.nextElementSibling.textContent.trim();

// if target was the None option, uncheck all others
if (targetElem === "None") {
chkboxArr.each(function() {
labelText = this.nextElementSibling.textContent.trim();

if (labelText !== "None") {
this.checked = false;
}
});
}
// if the target was anything BUT the None option, uncheck None
else {
chkboxArr.each(function() {
labelText = this.nextElementSibling.textContent.trim();

if (labelText === "None") {
this.checked = false;
}
});
}
};

(通过 Controller ) - html代码:
      <div ng-repeat="investmentObjective in fieldMappings.secondaryInvestmentObjectiveMap">
<input checkbox-group
type="checkbox"
name="secondaryInvestmentObjective"
ng-click="validationfunc('secondaryInvestmentObjective', $event)"
validationfunc="clearOnNone('secondaryInvestmentObjective', $event)"
fieldobj="investmentObjective"
destarray="suitabilityHolder.suitability.secondaryInvestmentObjective" />
<label class="checkbox-label"
popover-title="{{investmentObjective.name}}"
popover="{{investmentObjective.help}}"
popover-trigger="mouseenter">{{investmentObjective.name}}
</label>
</div>

(通过 Controller ) - 指令代码:
.directive("checkboxGroup", function () {
return {
restrict: "A",
scope: {
destarray: "=", // the source of all the checkbox values
fieldobj: "=", // the array the values came from
validationfunc: "&" // the function to be called for validation (optional)
},
link: function (scope, elem, attrs) {
if (scope.destarray.indexOf(scope.fieldobj.id) !== -1) {
elem[0].checked = true;
}
elem.bind('click', function () {
var index = scope.destarray.indexOf(scope.fieldobj.id);
if (elem[0].checked) {
if (index === -1) {
scope.destarray.push(scope.fieldobj.id);
}
}
else {
if (index !== -1) {
scope.destarray.splice(index, 1);
}
}
});
}
};
})

然后我决定我讨厌 event.target.nextElementSibling.textContent.trim()行...我觉得我应该仔细检查所有这些方法是否存在,或者使用 try/catch .所以我重写了指令以包含来自 Controller 的逻辑:

(通过指令) - html代码:
      <div ng-repeat="otherInvestment in fieldMappings.otherInvestmentsMap">
<input type="checkbox"
checkbox-group
groupname="otherInvestment"
labelvalue="{{otherInvestment.name}}"
fieldobj="otherInvestment"
destarray="suitabilityHolder.suitability.otherInvestment" />
<label class="checkbox-label"
popover-title="{{otherInvestment.name}}"
popover="{{otherInvestment.help}}"
popover-trigger="mouseenter">{{otherInvestment.name}}
</label>
</div>

(通过指令) - 指令代码:
.directive("checkboxGroup", function () {
return {
restrict: "A",
scope: {
destarray: "=", // the source of all the checkbox values
fieldobj: "=", // the array the values came from
groupname: "@", // the logical name of the group of checkboxes
labelvalue: "@" // the value that corresponds to this checkbox
},
link: function (scope, elem, attrs) {
// Determine initial checked boxes
// if the fieldobj.id exists in the destarray, check this checkbox
if (scope.destarray.indexOf(scope.fieldobj.id) !== -1) {
elem[0].checked = true;
}

// Update array on click
elem.bind('click', function () {
// store the index where the fieldobj.id exists in the destarray
var index = scope.destarray.indexOf(scope.fieldobj.id),
// get the array of checkboxes that form this checkbox group
chkboxArr = $('input[groupname^=' + scope.groupname + ']');

// Add if checked
if (elem[0].checked) {
if (scope.labelvalue === "None") {
// loop through checkboxes and uncheck all the ones that are not "None"
chkboxArr.each(function() {
// have to noodle through the checkbox DOM element to get at its attribute list
// - is there a cleaner way?
var tmpLabelValue = this.attributes.labelvalue.nodeValue.trim();
if (tmpLabelValue !== "None") {
this.checked = false;
}
});
}
// if the target was anything BUT the None option, uncheck None
else {
chkboxArr.each(function() {
var tmpLabelValue = this.attributes.labelvalue.nodeValue.trim();

if (tmpLabelValue === "None") {
this.checked = false;
}
});
}

if (index === -1) {
// add the id to the end of the dest array
// **will not maintain original order if several are unchecked then rechecked**
scope.destarray.push(scope.fieldobj.id);
}
}

// Remove if unchecked
else {
if (index !== -1) {
scope.destarray.splice(index, 1);
}
}
});
}
};
})

回想起来,我想我更喜欢将所有代码都放在一个指令中,尽管我认为它比通过 jQuery 在 Controller 中进行所有处理更不直观和更复杂。它从 Controller 中删除了 clearOnNone() 函数,这意味着在 html 标记和指令中处理此功能的所有代码。

我不喜欢 this.attributes.labelvalue.nodeValue.trim() 这样的代码,我仍然在我的指令中结束了。对于像我这样的场景,业务部门有某些要求(没有其他方式)是乏味和繁琐的,我不知道真的有一种“干净”的方式来编码。

关于angularjs - 使用 Angular 指令进行复杂表单验证/GUI 操作的优缺点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19190267/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com