3

HasOpenIssuesネストされたobservableArrayのいずれかのメンバーが条件を満たし、それを機能させることができない場合に更新するUI要素にバインドする計算されたオブザーバブルを実装しようとしています。KO 2.2.0 を使用しています。

私のビューモデルには、 Visitsの observableArray があります。各Visitには ObservableArray のIssueがあります。各Issues配列には、観測可能なIsFixedプロパティを持つIssueのインスタンスを含めることができます。また、Visits配列の最後のVisitを返す、計算された監視可能なLatestVisitもあります。

function myVM( initialData ) {
    var self = this;

    var Issue = function( id, isFixed, description ) {
        var self = this;
        self.Id             = id;
        self.IsFixed        = ko.observable( isFixed );
        self.Description    = ko.observable( description );
    };
    var Visit = function( id, visitDate, issues ) {
        var self = this;
        self.Id             = id;
        self.VisitDate      = ko.observable( visitDate );
        self.Issues         = ko.observableArray([]);

        // init the array
        issues && ko.utils.arrayForEach( issues, function( issue ) {
            self.addIssue( issue.Id, issue.Fixed, issue.Description );
        });
    }
    Visit.prototype.addIssue    = function( id, isFixed, description ) {
        this.Issues.push( new Issue( id, isFixed, description ) );
    };

    self.LatestVisit                = ko.computed( function() {
        var visits = self.Visits();
        return visits[ visits.length - 1 ];
    });
... vm continues

これらはすべて空で始まりko.applyBindings()、 I の前に、サーバーからいくつかの初期データを取得し、それを引数としてビューモデルに渡します。ビューモデルはそれを使用して、さまざまなオブザーバブルを初期化します。

... continued from above...
    self.init = function() {
        // init the Visits observableArray
        ko.utils.arrayForEach( initialData.Visits, function( visit ) {
            self.Visits.push( new Visit( visit.Id, visit.InspectionDateDisplay, visit.Issues ) );
        });
        ... more initialization...
    };
    self.init();
}

function registerVM() {
    vm = new myVM( initialDataFromServer );
    ko.applyBindings( vm );
}

そのため、プロセスのある時点で、LatestVisit配列Visitsにまだデータが入力されていないため、 も、Issuesその親Visitがまだデータに入力されていないため、配列も確認できません。HasOpenIssues初期化後、これらの構造にはデータが含まれているため、初期データの状態を反映するように更新する必要があります。

次に、ユーザーが に新規を追加IssuesLatestVisit、新規または既存Issuesを としてマークできるようにしますFixed。ですから、私HasOpenIssuesもそれらの変化に対応する必要があります。

HasOpenIssuesビューモデルのルート、Visits配列、Visitプロトタイプ、および計算されたものに直接プロパティとして計算されたものを追加しようとしましたがLatestVisit、何も機能しません。次のようになります。

    self.LatestVisit().HasOpenIssues = ko.computed( function() {
        var unfixed = ko.utils.arrayFirst( this.Issues(), function( issue ) {
            return issue.IsFixed == false;
        });
        console.log('HasUnfixedIssues:', unfixed);
        if ( unfixed ) { return true; }
    });

初期化の前に実行させると、いくつかのバリエーションが得られます

Uncaught TypeError: Object [object Window] has no method 'Issues' 

, root, { deferEvaluation: true }または、計算された関数呼び出しに引数を追加すると、

Uncaught TypeError: Cannot set property 'HasUnfixedIssues' of undefined 

のように() を省略した場合、次のようself.LatestVisit.HasOpenIssuesになります。

Uncaught TypeError: Object [object Window] has no method 'Issues' 

遅延オプションを使用しない場合。Issues追加すると初期化でエラーが出なくなりましたが、後で更新しても何も起こりません。

これを実装する方法に関するアドバイスはありますか?

ありがとう!

4

1 に答える 1

1

HasOpenIssuesすべての訪問のプロパティを作成します。そうすれば、最新の問題だけでなく、訪問に未解決の問題があるかどうかを確認できます。

function Visit(id, visitDate, issues) {
    this.Id             = id;
    this.VisitDate      = ko.observable(visitDate);
    this.Issues         = ko.observableArray();

    this.HasOpenIssues  = ko.computed(function() {
        var unfixed = ko.utils.arrayFirst(this.Issues(), function (issue) {
            return !issue.IsFixed();
        });
        return unfixed !== null;
    }, this);

    // init the array
    this.Issues(ko.utils.arrayMap(issues, function (issue) {
        return new Issue(issue.Id, issue.Fixed, issue.Description);
    }));
}

このように、問題がなくても、プロパティをundefined値に追加しようとしているわけではありません。

わざとデモ1


最新の訪問のみを気にする場合は、HasOpenIssuesプロパティを に添付することをお勧めしますLatestVisit。あなたはそれを正しくしなければなりません。最初のものがあるかどうかを確認してLatestVisitから、適切な値を返します。それ以外の場合は、デフォルト値 (この場合は false) を返します。

this.LatestVisit.HasOpenIssues  = ko.computed(function() {
    var visit = this.LatestVisit();
    if (!visit) {
        return false;
    }
    var unfixed = ko.utils.arrayFirst(visit.Issues(), function (issue) {
        return !issue.IsFixed();
    });
    return unfixed !== null;
}, this);

わざとデモ2

于 2013-01-19T06:32:28.913 に答える