Passing variables between KnockoutJS and AngularJS

后端 未结 1 1976
滥情空心
滥情空心 2020-12-22 05:35
  1. I am using Knockout in my SPA dashboard creation. Its working good.But we need to add more and more complex things in our dashboard, so we planned to develop the re

相关标签:
1条回答
  • 2020-12-22 05:59

    Mixing KnockoutJS and AngularJS in one application is a big red flag. Be sure you understand what you're doing, or you'll probably be better off rewriting the KO parts in Angular.

    Having said that, I can try to answer the question you're asking, though not in the context of the code snippet you provided (which is very unclear).

    There are three main ways KO can interact with Angular (which is the direction you seem to be asking about):

    1. They each control their own piece of the DOM. KO will "notify" Angular through Javascript code. This would be the preferred situation.
    2. They each control their own piece of the DOM. KO will "notify" Angular by influencing a piece of the DOM actually controlled by Angular.
    3. They have shared control of the same piece of the DOM. KO "notifies" Angular automatically because it will update the DOM when a variable changes, and Angular's two-way bindings pick this up.

    Option 2 and 3 are a recipe for disaster. They can be done, but are that bad I'll leave creating a PoC as an excercise for the reader.

    That leaves option 1, which in specific cases can actually be useful. To do so you need these ingredients:

    • Within Angular's scope a reference to the KO ViewModel;
    • A subscription on the relevant part of KO's ViewModel;
    • A call to $scope.$apply no notify Angular the KO subscription callback has changed the scope.

    Here's an exmaple:

    var ViewModel = function() {
      this.name = ko.observable("");
    };
    
    var vm = new ViewModel();
    
    angular.module("demoApp", [])
      .controller("myCtrl", ["$scope", function($scope) {
        $scope.name = vm.name();
      
        vm.name.subscribe(function(newVal) {
          $scope.$apply(function() {
            $scope.name = newVal;
          });
        });
      }]);
    
    ko.applyBindings(vm, document.getElementById("knockoutArea"));
    div { margin: 5px; padding: 5px; border: 1px solid #edd; background-color: #fee; }
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    
    <div id="knockoutArea">
      <strong>Knockout</strong><br>
      Type your name: <input data-bind="textInput: name">
    </div>
    
    <div id="angularArea" ng-app="demoApp" ng-controller="myCtrl">
      <strong>Angular</strong><br>
      We know your name is: <strong>{{ name }}</strong>
    </div>

    As an alternative, given that Angular seems to be your way forward, you may want to invert the dependency. Give KO a reference to Angular and make that "legacy" part of your code call updates on the Angular scopes. This makes your KO code a lot dirtier, but keeps your future codebase cleaner.

    0 讨论(0)
提交回复
热议问题