Javascript angularjs模型中的更改仅在单击某个位置时渲染

Javascript angularjs模型中的更改仅在单击某个位置时渲染,javascript,angularjs,firebase,firebase-realtime-database,Javascript,Angularjs,Firebase,Firebase Realtime Database,我正在使用firebase和angular js开发搜索建议功能。基本上,在搜索输入框的键向上时,我调用以下函数: scope.suggestString = {}; scope.search = function(){ scope.suggestString = {}; firebaseDb.ref("users") .orderByChild("Name") .startAt(scope.searchedString

我正在使用firebase和angular js开发搜索建议功能。基本上,在搜索输入框的键向上时,我调用以下函数:

scope.suggestString = {};

    scope.search = function(){
        scope.suggestString = {};

        firebaseDb.ref("users")
        .orderByChild("Name")
        .startAt(scope.searchedString)
        .endAt(scope.searchedString + "\uf8ff")
        .on("value", function(snapshot) {
            snapshot.forEach(function(childSnapshot) {
                if(scope.suggestString.hasOwnProperty(childSnapshot.key) == false){
                    scope.suggestString[childSnapshot.key] = childSnapshot;
                }
            });
        });
    }
HTML:


代码运行正常,调用到firebase并获取记录,但我必须单击搜索输入框中的某个位置才能显示建议。
我试过使用scope.$apply(),但它不起作用。它说已经在应用scope了

也许您可以使用类似于:

<input ng-model="searchedString" ng-model-options="{debounce: 1000}" type="text"> 
scope.$watch('searchedString', (newVal,oldVal)=>{
     scope.suggestString = {};

        if(scope.searchedString.length <3){
            return;
        }

        firebaseDb.ref("users")
        .orderByChild("Name")
        .startAt(scope.searchedString)
        .endAt(scope.searchedString + "\uf8ff")
        .on("value", function(snapshot) {
            snapshot.forEach(function(childSnapshot) {
                if(scope.suggestString.hasOwnProperty(childSnapshot.key) == false){
                    scope.suggestString[childSnapshot.key] = childSnapshot;
                }
            });
        });
});

在输入框上,输入延迟1秒后,将使用输入元素中的搜索字符串更新ng模型(searchString)

之后,您可以放置类似以下内容:

<input ng-model="searchedString" ng-model-options="{debounce: 1000}" type="text"> 
scope.$watch('searchedString', (newVal,oldVal)=>{
     scope.suggestString = {};

        if(scope.searchedString.length <3){
            return;
        }

        firebaseDb.ref("users")
        .orderByChild("Name")
        .startAt(scope.searchedString)
        .endAt(scope.searchedString + "\uf8ff")
        .on("value", function(snapshot) {
            snapshot.forEach(function(childSnapshot) {
                if(scope.suggestString.hasOwnProperty(childSnapshot.key) == false){
                    scope.suggestString[childSnapshot.key] = childSnapshot;
                }
            });
        });
});
scope.$watch('searchedString',(newVal,oldVal)=>{
scope.suggestString={};

如果(scope.searchedString.lengthAngular不知道此异步调用,则必须触发摘要。在收到响应后,通过调用
$evalAsync
可以安全地执行此操作,而不会出现控制台错误:

// ...
.on("value", function (snapshot) {
  scope.$evalAsync(function () {
    snapshot.forEach(function (childSnapshot) {
      if (scope.suggestString.hasOwnProperty(childSnapshot.key) == false) {
        scope.suggestString[childSnapshot.key] = childSnapshot;
      }
    })
  });
});
但是我怀疑
scope.$apply
也可以,如果你像我上面所做的那样在循环之外做的话


另一个选项是将所有firebase功能包装成一个单独的功能(可能在服务中),并使用
$q
服务从该函数返回一个承诺,并解析firebase响应。这样,您就不必手动触发摘要,因为Angular知道
$q
服务。

是我一直在寻找的东西,搜索现在很顺利。

firebase代码的哪一部分是使这是一个请求?@FrankModica再次更新了问题,错误地添加了ng click而不是ng keyup。对db的调用进行得很顺利,但渲染需要clicksYeah我想问的是哪个部分是异步调用的实际响应,因为这可能是您必须用
$apply
包装的部分,因为Angular可能不知道如果这些请求未通过
$http
服务的快照,则会执行这些请求。forEach(函数(childSnapshot){'是异步调用的回调,顺便说一句,它在使用作用域后立即工作。$apply在此代码内。但是控制台也显示错误[$rootScope:inprog]$apply已经在进行中。不要在forEach回调中触发摘要循环,在forEach回调之后立即触发它。我真的建议使用我的解决方案,因为你应该避免使用$scope。$apply
$evalAsync
有点像safe apply的内置版本。不需要引入外部代码。@pegla
$apply
?它的目的不是警告Angular来自Angular世界之外的更改吗?处理外部插件的指令一直都在使用它。你确定这会起作用吗?也许我遗漏了一些东西,但如果实际问题是Angular不知道发生了异步进程,那么响应何时发生到达时,
.on(…)
仍将在Angular的摘要周期之外运行,需要触发,否?我可能会误解,但即使如此,我认为您也不需要手动触发摘要周期,我宁愿使用Promissions.then()而不是.on()它应该在没有任何手动摘要cycleYeah的情况下很好地更新suggestString,要做到这一点,我认为您必须将整个firebase调用封装在一个函数中,该函数从
$q
服务返回一个承诺。