0

所以我已经来回讨论了很长时间了,所以我会直奔主题。

我正在创建一个基于 HotTowel 模板的应用程序,所以我使用了敲除、微风、Q 等。我使用微风查询从服务器获取一些数据,然后将该数据加载到第一个选择中(如选项)。这会更改 selectedModel 可观察对象和订阅触发器(订阅是当前的“解决方案”,我使用了数据绑定等,结果相同)。然后订阅获取新的 selectedModel 值并使用它来获取第二个 observable 的数据。此查询也会通过,结果存储在 modelProperties 可观察数组中,但 UI 不会更新第二个选择(它是空的)。奇怪的是,按 ctrl + F5 (我连续尝试了大约 50 次)总是可以正确填充它,但永远不会在第一次加载时。

TLDR;2 选择,第一个的选定选项定义了对第二个选项的查询。查询工作,可观察对象被填充,第一次选择总是被填充,第二次永远不会在第一次启动时,但总是在下面的 ctrl+F5 上。

以下是有关这部分应用程序的一些片段: 视图模型:

define(['services/logger', 'services/datacontext'], function (logger, datacontext) {
    var models = ko.observableArray();
    var modelProperties = ko.observableArray();
    var selectedModel = ko.observable();
    var init = true;

    function activate() {
        logger.log('Search View Activated', null, 'search', true);
        return datacontext.getModels(models);
    }

    var sub = selectedModel.subscribe(function (newValue) {
        return datacontext.getModelProperties(modelProperties, newValue);
    });

    var vm = {
        activate: activate,
        models: models,
        selectedModel: selectedModel,
        modelProperties: modelProperties,
        title: 'Search View'
    };

    return vm;

视图的代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body id="one">
    <select id="entitySelect" class ="entitySelect" name="first"
        data-bind="options: models, value: selectedModel">
    </select>
    <select id="propertySelect" class ="propertySelect" data-bind=
    'options:modelProperties'></select>
</body>
</html>

以及数据上下文中的方法:

        var getModels = function (modelsObservable) {
        var query = EntityQuery.from('Models');
        return manager.executeQuery(query)
            .then(querySucceeded)
            .fail(queryFailed);

        function querySucceeded(data) {
            logger.log("Query succeeded", true);
            logger.log(data);
            if (modelsObservable) {
                modelsObservable(data.results);
            }
            logger.log('Retrieved [Models] from remote data source',
                data, true);
        }
        function queryFailed(data) {
            logger.log(data.toString(), data, true);
        }
    };

    var getModelProperties = function (propertiesObservable,modelName) {
        var query = EntityQuery.from('ModelProperties').withParameters({ name: modelName });
        return manager.executeQuery(query)
            .then(querySucceeded)
            .fail(queryFailed);

        function querySucceeded(data) {
            logger.log("Query succeeded", null, true);
            logger.log(data);
            if (propertiesObservable) {
                propertiesObservable(data.results);
            }
            logger.log('Retrieved [Properties] from remote data source',
                data, true);
        }
        function queryFailed(data) {
            logger.log(data.toString(), data, true);
        }
    };

我想再次指出,所有查询都通过了,并且 observableArrays 确实填充了结果(使用 .peek() 检查)。

这里有一些截图可以澄清问题:从 VS 首次启动时:http: //i.imgur.com/8Gd53Yh.png

然后,ctrl+F5 http://i.imgur.com/vzO8d70.png

我已经尝试了几乎所有我能想到的东西,并在谷歌上搜索了所有想到的东西,但无济于事。任何帮助将不胜感激!另外,这是我在这里的第一篇文章,如有错误,我深表歉意!

4

2 回答 2

1

这里有一些评论——

你的观点毫无意义。如果您使用的是 HotTowel 模板之类的东西,那么那里不需要很多额外的标记,考虑到您很可能使用 Durandal.js 进行合成,而额外的标记可能会伤害您。

如果您确实或多或少地加载了“子视图”,那么它应该是这样的 -

<select id="entitySelect" class ="entitySelect" name="first" data-bind="options: models, value: selectedModel"></select>
<select id="propertySelect" class ="propertySelect" data-bind='options:modelProperties'></select>

接下来,如果您使用的是级联下拉菜单,我之前已经提到过这种方法,我强烈建议大家使用。使用 ko.computed 让您的第二个依赖于您的第一个。

var models = ko.observableArray();
var modelProperties = ko.computed(function () {
    var modelArr = ko.observableArray();
    if (!selectedModel()) { return modelArr; }
    datacontext.getModelProperties(modelArr, selectedModel().then(function() { return modelArr(); });
});

现在 modelProperties 将为空,直到您选择一个模型,然后它将出去并获取该模型的属性。

了解您正在使用的函数声明之间的区别也很重要。var myFunc = 函数 () {}; 是一个构造函数,将立即评估视图模型实例化。function myFunc () {} 是一个标准函数,将等到被调用后再评估。

于 2013-08-09T03:12:53.890 回答
0

我对这个问题有点晚了,但这就是我能够完成级联下拉菜单的方式。我希望这可以帮助任何一直在努力解决这个问题的人。

视图模型

        define(['durandal/system', 'durandal/app', 'jquery', 'knockout', 'services/projectdetailmanager'],
function (system, app, $, ko, pdm) {

        var projectValues = ko.observableArray();
        var taskValues = ko.observableArray();

        activate = function () {
         return pdm.getAllContracts(projectValues);
        }


        selectedProject.subscribe(function () {
        pdm.getSelectedTasks(taskValues, selectedProject().iD()).then(function () {
            return taskValues;
        });
    });

         return {
        activate: activate,            
        projectValues: projectValues,
        selectedProject: selectedProject,
        taskValues: taskValues,
        selectedTask: selectedTask
    };
  });

HTML

<div>
    <table>
        <thead>
            <tr>
                <td style="font-weight:bold;">Projects</td>
                <td style="font-weight:bold;">Tasks</td>                
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>
                    <select data-bind='options: projectValues, optionsText: "name", optionsCaption: "Select...", value: selectedProject'> </select>
                </td>
                <td>
                    <select data-bind='options: taskValues, optionsText: "name", optionsCaption: "Select...", value: selectedTask, event: { change: yourChangeEvent}'> </select>
                </td>
            </tr>
        </tbody>
    </table>        
</div>

数据上下文/服务

        function getAllContracts(projectValues) {
        var query = breeze.EntityQuery
        .from("Contract");

        return manager.executeQuery(query)
        .then(querySucceeded)
        .fail(queryFailed);

        function querySucceeded(data) {
            system.log("Query succeeded");
            system.log(data);

            if (projectValues) {
                projectValues(data.results);
            }
        }
        function queryFailed(data) {
            system.log("Query failed");
        }

    };

    function getSelectedTasks(taskValuesArr, projectID) {
        var query = breeze.EntityQuery
        .from("Task")
        .where("contractID", "==", projectID);

        system.log("Within getSelectedTask; projectID = " + projectID);

        return manager.executeQuery(query)
        .then(querySucceeded)
        .fail(queryFailed);

        function querySucceeded(data) {
            system.log("Query succeeded");
            system.log(data);

            if (taskValuesArr) {
                taskValuesArr(data.results);
            }
        }
        function queryFailed(data) {
            system.log("Query failed");
        }

    };    
于 2013-11-28T02:43:20.240 回答