gpt4 book ai didi

ember.js - 如何使用 Ember 为 Solr 服务构建类似 google 的搜索界面

转载 作者:行者123 更新时间:2023-12-02 21:36:02 25 4
gpt4 key购买 nike

我是 Ember 的新手,正在尝试为 Solr API 实现类似 Google 的搜索界面。即我希望结果在您键入时在页面上自动更新。

我的第一个想法是创建一个可重用的 TextSearch CollectionView,带有两个 subview SearchInput 和 SearchResults。

输入 SearchInput 将触发一个事件,该事件将被 TextSearch CollectionView 捕获,这将更新 SearchResult 子元素。

我的事件生成正常,但 TextSearch ContainerView 无法使用操作、函数或事件管理器拦截事件。但是,由于某种原因,我可以拦截 IndexController 中的事件,但我需要在可重用的 TextSearch CollectionView 中处理它(我认为)。

最后,我无法更新 SearchResults 中的 View (当我尝试处理 IndexController 中的事件时),并且 SearchResult 模型不会在页面加载时触发。

我是 Ember 的新手,所以我确定我在这里做了一些愚蠢的事情。走到这一步还有很长的路要走。

任何建议将不胜感激!

粘贴箱:
http://jsbin.com/ezomOkO/3/edit

HTML:

<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="index">
{{view App.TextSearchView }}
</script>

<script type="text/x-handlebars" data-template-name="textSearch">
{{view App.SearchInputView }}
{{view App.SearchResultsView }}
</script>

<script type="text/x-handlebars" data-template-name="searchInput">
{{input type="text" value=query size="50"}}
</script>

<script type="text/x-handlebars" data-template-name="searchResults" >
<ul>
{{#each concept}}
<li>{{title}}</li>
{{else}}
Sorry, nobody is here.
{{/each}}
</ul>

Javascript:
App = Ember.Application.create();

App.ApplicationController = Ember.Controller.extend({
appName: 'Snomed Search'
});

App.Router.map(function() {
this.route("index", {path: "/"});
});

// INDEX
App.IndexRoute = Ember.Route.extend({
});
App.IndexController = Ember.Controller.extend({
});

//TEXT SEARCH
App.TextSearchView = Ember.View.extend({
actions:{
search: function(search) {
this.get('controllers.searchResults').set('model', App.TextSearch.find(search));
return false;
}
},
needs: "searchResults",
templateName: 'textSearch'
});

// SEARCH INPUT
App.SearchInputController = Ember.Controller.extend({
query: 'Family'
});

App.SearchInputView = Ember.View.extend({
templateName: 'searchInput',
keyUp: function(evt) {
this.get('controller').send('search', this.get('controller.query'));
}
});

// SEARCH RESULTS
App.SearchResultsController = Ember.Controller.extend({
model: function(){
return App.TextSearch.find('Family');
},
afterModel: function(posts, transitions){
alert('model');
},
isPublic: true
});

App.SearchResultsView = Ember.View.extend({
templateName: 'searchResults'
});


App.SearchResults = Ember.Object.extend({
total: 0,
start: 0,
concepts: Ember.A()
});

App.Concept = Ember.Object.extend({
id: null,
title: null,
active: null,
effectiveTime: null
});

App.TextSearch = Ember.Object.extend({});

App.TextSearch.reopenClass({
find: function(searchString){
return Ember.Deferred.promise(function(p) {
p.resolve($.getJSON("http://solr.sparklingideas.co.uk/solr/concept/select?q=title:" + searchString + "&wt=json&indent=true")
.then(function(solr) {
var returned = App.SearchResults.create();
returned.total = solr.response.numFound;
returned.start = solr.response.start;
solr.response.docs.forEach(function (doc) {
var concept = App.Concept.create();
concept.id = doc.id;
concept.title = doc.title;
concept.active = doc.active;
concept.effectiveTime= doc.effectiveTime;
returned.concepts.push(concept);
});
return returned;
}) //then
);//resolve
});//deferred promise
}//find
});//reopen

更新

非常感谢你的帮助,杰里米,这就是我需要的所有信息。杰出的。

以下是一些经验教训:
  • 在使用结果之前,您必须等待 JSON promise 解析,如下所示:
    search: function(search) {
    var results = App.TextSearch.find(search);
    var _this = this;
    // results is a jquery promise, wait for it to resolve
    // Ember can't resolve it automatically
    results.then(function(results){
    _this.get('controllers.searchResults').set('model', results);
    });
    return false;
    }
  • 我不知道 View 、渲染和 Controller 之间的区别(它的文档并不完整,但谷歌搜索会告诉你)。但是这些与“部分”助手有什么关系呢?不确定。
  • 通过添加 '&json.wrf=?'到 Solr URL 的末尾,您可以避免由于 XSS 安全性而在浏览器中阻止调用。
  • 关于如何从 View 中引用模型,我对 ember 文档感到非常困惑。这是正确的方法(对于此示例):
    <script type="text/x-handlebars" data-template-name="searchResults" >
    Total : {{model.total}}
    <ul>
    {{#each model.concepts}}
    <li>{{title}}</li>
    {{else}}
    Sorry, nobody is here.
    {{/each}}
    </ul>
    </script>
  • 我的事件没有被 View Controller 捕获,因为通过在模板中使用 {{view}} 助手,没有 Controller (!)。改用 {{render}} 助手。

  • 对于建议的解决方案中的评论,只是一个小的更正,供 future 的读者使用:
        App.SearchResultsController  = Ember.Controller.extend({
    // This controller could be removed.
    // Ember will auto generate one for you.
    });

    实际上,删除此 Controller 会导致 Javascript 错误:
    Assertion failed: <App.TextSearchController:ember242> needs controller:searchResults but it does not exist 

    因为 SearchInputController 的需要属性。不过,在最后一个示例中,我最终从输入 Controller 中删除了对 searchResults 的依赖。

    我相信 Ember 现在需要将事件处理程序包装在 'actions: {}' 参数中,如下所示:
        actions:{
    search: function(search) {
    var results = App.TextSearchController.find(search);
    var _this = this;
    // results is a jquery promise, wait for it to resolve
    // Ember can't resolve it automatically
    results.then(function(results){
    _this.get('controllers.searchResults').set('model', results);
    });
    return false;
    }
    }

    请注意:

    JSBin 使用 EmbeJS RC6,它已经有几个月的历史了。上述将事件处理程序包装在“action”属性中的更改似乎是在 RC6 之后引入的。如果您使用的是最新版本的 Ember(正如您应该的那样),那么您的(事件)代码将无法在 JSBin(使用默认的 Ember 库)中运行。但是,如果您不使用操作包装器,那么您的代码将无法在您的浏览器中运行。嗯……见 github.com/emberjs/ember.js/releases

    在下面的 JSBin 示例中,我因此从事件处理程序中删除了“action:”标记,因此应用程序将运行。

    我还做了一些小的设计更改:
  • 我将搜索事件处理程序从 InputController 移动到
    改为包含 TextSearchController,以便解耦
    来自 SearchResultsController 的 InputController。
  • 我也删除了
    在页面加载时进行初始搜索,因此用户从一张白纸开始。
  • 最后,我删除了 TextSearch 对象,并移动了 solr
    而是集成到 TextSearchController 中。

  • 最终版本可以在这里找到:
    http://jsbin.com/ezExeCI/1/

    非常感谢您的帮助,杰里米。没有你我做不到。我会确保提前支付。

    非常感谢!

    最佳答案

    您在 jsbin 中相当接近,并且有两种不同的方法可以解决此问题。

  • 不要直接使用Views,使用render反而。通常,您不想直接实例化 View 。当您这样做时,您最终不会为每个 View 使用不同的 Controller 。相反,您的每个 View 最终都连接到渲染开始的主 Controller 。在这种情况下 App.IndexController .比直接使用 {{view App.TextSearchView}} 实例化 View 更好是使用 {{render "textSearch"}} .使用 render意味着你让 Controller 支持你的每个不同的 View /模板。如果你把 search方法在 App.SearchInputController然后它会被调用。

    这是一个 render基于jsbin:http://jsbin.com/aNowEZO/1/edit
  • 继续使用 View 。如果您真的想继续直接实例化 View ,请注意上下文中的 Controller 是您的 App.IndexController .在这种情况下,您的 search方法,以及您的 query属性(property)都需要住上App.IndexController ,而您不需要 App.SearchInputControllerApp.SearchResultsController因为它们从未被 Ember 使用过。

    这是一个 jsbin 显示:http://jsbin.com/EMexuXU/1/edit

  • 另外值得注意的是 modelafterModel是在 Route 上调用的回调,不是 Controller .

    最后,您会看到由于跨域限制,搜索实际上在“继续使用 View ”jsbin 中不起作用。你会看到这个错误: XMLHttpRequest cannot load http://solr.sparklingideas.co.uk/solr/concept/select?q=title:Familys&wt=json&indent=true. Origin http://run.jsbin.com is not allowed by Access-Control-Allow-Origin.要解决此问题,您需要从“solr.sparklingideas.co.uk”为您的应用程序提供服务,或者您需要让 Solr 服务器发送适当的 CORS header 。

    好在 Solr 可以发送 jsonp,不受跨域限制,添加 &json.wrf=?到网址。 jQuery 会自动为您处理 jsonp 响应。 “不要使用 View ”jsbin 包含 jsonp 修复和其他一些随机位,我必须调整这些位才能使事情正常工作。 ( http://jsbin.com/aNowEZO/1/edit )

    关于ember.js - 如何使用 Ember 为 Solr 服务构建类似 google 的搜索界面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18710484/

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