3

私は現在、ボタンをクリックするだけでブラウザで新しいウィンドウを開く必要があるアプリケーションに取り組んでいます。ユーザーがメインウィンドウのテキストボックスに入力すると、それに応じて新しいウィンドウが更新されます。以前にノックアウトを使用しましたが、何らかの理由で2番目のWindowsビューを更新するのに問題があります。これが私の現在のコードです。

//main.js
   $(function () {
        var viewModel = new ViewModel();
        ko.applyBindings(viewModel);
        var newwindow;
        $("#new-window-btn").click(function () {
            newwindow = window.open("a/path/to/newwindow.html", "New Window","status=1,width=350,height=350");
            newwindow._ViewModel = viewModel;
        });

    });

    function ViewModel() {
        var self = this;
        self.textbox = ko.observable("");
    };

これはindex.htmlであり、新しいウィンドウを開く非常に基本的なボタン、ユーザーが入力するテキストボックス、および私が夢中でないことを示すスパンタグが含まれています。

//index.html
<div id="new-window-btn" class="btn">new window</div>
<textarea cols="3" rows ="3" data-bind="value:textbox,valueUpdate:'afterkeydown'"></textarea>
<span data-bind="text: textbox"></span>

これは、ユーザーがindex.htmlの新しいウィンドウボタンをクリックしたときにポップアップする2番目のウィンドウのコードです。

//newwindow.html
    <script type="text/javascript">
        $(function () {
            var viewModel = window._ViewModel;
            ko.applyBindings(viewModel);
            $("#alert-viewModel").click(function () {
                alert(viewModel.textbox());
            });
        });
    </script>
<span data-bind="text:textbox()"></span>
<div id="alert-viewModel" class="btn">show texbox value</div>

ユーザーがメインページのテキストボックスに入力すると、そのページのスパンタグが自動的に更新されます。ユーザーが新しいウィンドウボタンをクリックすると、新しいウィンドウがポップアップし、ユーザーが入力したテキストが表示されます。ユーザーがメインウィンドウのテキストボックスに入力し続けると、セカンダリウィンドウのスパンタグは更新されません。ただし、ユーザーが[texbox値の表示]ボタンを押すと、テキストがアラートボックスに表示され、更新されます。だから私の質問は、ViewModelが明らかに更新されたときに2番目のウィンドウのスパンタグが更新されないのはなぜですか([texbox値の表示]ボタンから表示された値のため)。

クイックコメント:何らかの理由でwindow.open( "somepath");を介してファイルにアクセスします。この質問のコンテキストでは、実際には正しく機能しません。新しいウィンドウファイルを小さなHTTPサーバーにロードし、「somepath」を実際のURLにする必要があることがわかりました。(これが、この質問に添付されたサンプルコードがない理由です)。

4

2 に答える 2

9

2つのウィンドウはko、同じビューモデルを共有する場合の同じインスタンスも共有する必要があります。これは、Knockoutの1つのインスタンスで作成されたオブザーバブルが、別のインスタンスでは機能しないためです。

これはを使用する例ですiframeが、同じ原則が以下に適用されますwindow.open

親: http: //jsfiddle.net/eZMTM/ ; 子: http: //jsfiddle.net/GrXhv/7/

親コード:

childWindow = ...;
childWindow.initChild(ko, viewModel);

子コード:

window.initChild = function(ko, viewModel) {
    window.ko = ko;
    ko.applyBindings(viewModel, document.body);
}
于 2013-03-26T10:50:52.920 に答える
1

Michaelが述べたように、次のように、開いたウィンドウの本体にバインディングを適用できます。

var mywindow = window.open('', '', 'height=400,width=600');
mywindow.document.write('<input id="testText" type="text" data-bind="textInput: text1"/>');
ko.applyBindings(viewmodel, mywindow.document);

ポップアップを使用した実用的な例を試してみたい場合は、ここにフィドルがあります。

以下のスニペットに完全なコードを添付しましたが、stackoverflowサンドボックスではポップアップが許可されていないため、ここのスニペットでは失敗します。まだ投稿にコードがあることは十分に価値があるようです。

PS:古いですが、これは私が得たグーグルの最初のヒットの1つなので、実用的な例を追加すると役立つと思いました...

$(function() {
  var viewModel = function() {
    var self = this;

    //creating our observables
    self.text1 = ko.observable("Hello World ...");
    self.text2 = ko.observable("... how's it going");

    //The magic happens here
    self.newKOWindow = function() {
      var mywindow = window.open('', '', 'height=400,width=600');

      //just adding the html boilerplate Part1
      mywindow.document.write('<html><head><title>The KO Popup</title>');
      mywindow.document.write('</head><body>');

      //manually creating the input the window      
      mywindow.document.write('<div class="dontCopyMe">');
      mywindow.document.write('<h2>A Manually created input which is bound</h2>');
      mywindow.document.write('<input id="testText" type="text" data-bind="textInput: text1"/>');

      //just adding the html boilerplate Part2      
      mywindow.document.write('</div>');
      mywindow.document.write('</body></html>');
      mywindow.document.close();

      //just copy our inputs into the new window
      $(".copyMe").clone().appendTo(mywindow.document.body);

      //copy our css
      $("#compiled-css").clone().appendTo(mywindow.document.head);

      //bind the viewmodel
      window.ko = ko;
      ko.applyBindings(self, mywindow.document.body);

      return true;
    }
  };

  model = new viewModel();
  ko.applyBindings(model);

});
.copyMe,
.dontCopyMe {
  border: 3px dashed limegreen;
  padding: 0.5rem;
  margin: 0.5rem;
  max-width: 30rem;
}

.dontCopyMe {
  border-color: grey;
}

h2 {
  margin: 0 0 0.5rem;
  font-size: 1rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<body>
  <div>
    <div class="copyMe">
      <h2>Our inputs (will be copied into the popup window)</h2>
      <input type="text" data-bind="textInput: text1" />
      <input type="text" data-bind="textInput: text2" />
    </div>
    <div class="copyMe">
      <h2>Same Inputs just to show this is working :)</h2>
      <input type="text" data-bind="textInput: text1" />
      <input type="text" data-bind="textInput: text2" />
    </div>
    <input id="NWO" type="button" value="NEW KO WIN OPEN" data-bind="click: newKOWindow" />
  </div>
</body>

于 2019-12-12T10:00:16.840 に答える