提前道歉,我不是一个非常有经验的JS程序员,使用AngularJS的经验更少,但我正在尝试对使用Angular 1.5.9和Smart Table显示数据库中的信息的遗留代码库进行一些改进。
我已经阅读了所有关于st-search、st-safe-src和st-table等的内容,但我在筛选我的表时遇到了麻烦,因为在显示底层数据之前,底层数据会发生转换。在我的例子中,ng-repeat变量是UUID,它有各种字段来保存事务信息,比如payee,它保存一个指向另一个数据库文档的UUID。在应用程序中,我们使用来自另一个控制器(dbCtrl.getPayeeName())的函数显示该收款人的名称,但底层数据是UUID。因此,当尝试使用智能表进行筛选时,它不会根据显示的名称进行筛选,并且仅当在筛选字段中输入UUID时才起作用。
一个小例子(去掉了很多中间的部分,但希望足以证明我的困惑):
<div class="account"
st-table="displayedTransactions"
st-safe-src="transactions"
disable-ng-animate>
...
<div><input st-search="payee" placeholder="search for payee" class="input-sm form-control" type="search"/></div>
...
<div ng-repeat="transaction in displayedTransactions track by transaction.id">
...
<div class="account__td" transaction-field-focus-name="payee">
{{dbCtrl.getPayeeName(transaction.payee)}}
</div>
...
</div>对于这种显示数据与底层数据不同的情况,有没有一种相对简单的方法可以让过滤起作用?根据我在文档中读到的内容,这听起来可能需要某种自定义插件,这听起来像是更多的工作,但我可能会弄清楚。我只是想看看在走那条路之前我是不是遗漏了什么。
发布于 2021-09-08 23:54:07
回到这一点上,我能够使用文档的Strict mode filtering部分中描述的st-set-filter属性以及2014年来自laurent的this helpful answer来完成我需要的东西。
实际上,我在html模板的table中添加了st-set-filter="transactionFilters",以及具有st-search="prop_to_search"属性的input标记。然后在我的应用程序模块中(我把它放在一个控制器中,不确定这是否完全正确),我定义了一个过滤器,如下所示。expression作为一个带有字符串值的对象传递到此代码中,因此,如果您有三个搜索字段,则会得到一个如下所示的对象:
{
"prop_to_search1": "value1",
"prop_to_search2": "value2",
"prop_to_search3": "value3"
}在filter函数中,我为可能传入的每个属性编写了一个if块,然后在其中执行自定义转换和模式匹配。这样,我可以完全控制最终的匹配,而不是搜索UUID,我可以执行类似$rootScope.dbCtrl.getPayeeName(uuidToSearch)的操作。在我的用例中,这都是可以接受的性能,但我可能会缓存这些数据库查找作为潜在的优化。
angular.module('myApp').filter('transactionFilters', function($rootScope, $filter){
return function(array, expression){
// console.log(`expression is: ${JSON.stringify(expression, null, 4)}`)
return array.filter(function(val, index){
// in this function's context, `expression` is an object with
// the active filters entered in each field; `val` is the data
// representation of each row of the table
// if this function returns true, the row will match and smart-table
// will show it, otherwise it will be hidden
// define matches all at once, check them all, then return
// a big logical AND on all of them
let accountMatch = true;
let payeeMatch = true;
let categoryMatch = true;
if (expression.account) {
uuidToSearch = val.account // this is the account UUID
strToSearch = $rootScope.dbCtrl.getAccountName(uuidToSearch).toLowerCase(); // convert to an account name (we could memoize this to improve performance)
if (strToSearch) {
// if the account had a name (it always should, but catch in case)
// then check if the row's account contains the text entered in the filter field
accountMatch = strToSearch.includes(expression.account.toLowerCase());
} else {
accountMatch = false;
}
}
if (expression.payee){
if (val.payee) {
uuidToSearch = val.payee
strToSearch = $rootScope.dbCtrl.getPayeeName(uuidToSearch).toLowerCase();
}
if (strToSearch) {
payeeMatch = strToSearch.includes(expression.payee.toLowerCase());
} else {
payeeMatch = false;
}
}
if (expression.category) {
if (val.category) {
strToSearch = $rootScope.dbCtrl.getCategoryName(val.category, val.date).toLowerCase()
categoryMatch = strToSearch.includes(expression.category.toLowerCase())
} else {
categoryMatch = false;
}
}
return (
accountMatch &&
payeeMatch &&
categoryMatch
)
})
}
});https://stackoverflow.com/questions/69069047
复制相似问题