所以我现在已经来回这么久了,所以我会谈到这一点。
我正在创建一个基于HotTowel模板的应用程序,所以我正在使用knockout,breeze,Q等。我正在使用一个轻微的查询来从服务器获取一些数据,然后我将这些数据加载到第一个选择(作为选项)。这会更改selectedModel observable和订阅触发器(订阅是当前的“解决方案”,我使用了数据绑定等具有相同的结果)。然后,订阅获取新的selectedModel值,并使用它来获取第二个observable的数据。此查询也会传递,结果存储在modelProperties可观察数组中,但UI不会更新第二个选择(它是空的)。奇怪的是,按ctrl + F5(我连续尝试了50次)总是正确地填充它,但从来没有在第一次加载。
TLDR; 2选择,第一个选择的选项定义第二个选项的查询。查询工作,observables填充,首先选择总是填充,第二次从不在第一次启动但总是在以下ctrl + F5。
以下是有关此应用程序的一些摘要: viewmodel:
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>
datacontext中的方法:
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
我已经尝试了几乎所有我能想到的东西,并用Google搜索了所想到的一切,但无济于事。任何帮助将不胜感激!另外,这是我在这里的第一篇文章,所以我为任何错误道歉!
答案 0 :(得分: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将为null,然后它会出去并获得该模型的属性。
理解您正在使用的函数声明之间的区别也很重要。 var myFunc = function(){};是一个构造函数,将在视图模型实例化时立即进行评估。 function myFunc(){}是一个标准函数,在评估之前会一直等到调用。
答案 1 :(得分: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>
的DataContext /服务
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");
}
};