最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to instantiate ng-controller based on a condition - Stack Overflow

programmeradmin2浏览0评论

I asked this question but the specific question I'm asking has changed dramatically.

I have a piece of code:

  <div ng-attr-controller="{{pings || 'PingsCtrl as pings' }}">
    <h1 ng-click="pings.press()">asdf</h1>
  </div>

This code is injected into two html pages. One page already calls PingsCtrl. The other doesn't. I'm really trying to keep this code DRY and I only want to have one reference of the code above.

How can I write the code above to generate ng-controller if PingsCtrl hasn't already instantiated.

Here are the two html pages.

HTML

// First page
<html ng-app="coolApp">
  <div ng-controller="PingsCtrl as pings">
    <div ng-attr-controller="{{pings || 'PingsCtrl as pings' }}">
      <h1 ng-click="pings.press()">asdf</h1>
    </div>
  </div>
</html>

// Second page
<html ng-app="coolApp">
  <div ng-attr-controller="{{pings || 'PingsCtrl as pings' }}">
    <h1 ng-click="pings.press()">asdf</h1>
  </div>
</html>

Javascript is here:

angular.module('coolApp', [])

.controller('PingsCtrl', function() {
  var vm = this;

  vm.press = function() {alert(123)};
})

What's wrong and how do I fix this?

I asked this question but the specific question I'm asking has changed dramatically.

I have a piece of code:

  <div ng-attr-controller="{{pings || 'PingsCtrl as pings' }}">
    <h1 ng-click="pings.press()">asdf</h1>
  </div>

This code is injected into two html pages. One page already calls PingsCtrl. The other doesn't. I'm really trying to keep this code DRY and I only want to have one reference of the code above.

How can I write the code above to generate ng-controller if PingsCtrl hasn't already instantiated.

Here are the two html pages.

HTML

// First page
<html ng-app="coolApp">
  <div ng-controller="PingsCtrl as pings">
    <div ng-attr-controller="{{pings || 'PingsCtrl as pings' }}">
      <h1 ng-click="pings.press()">asdf</h1>
    </div>
  </div>
</html>

// Second page
<html ng-app="coolApp">
  <div ng-attr-controller="{{pings || 'PingsCtrl as pings' }}">
    <h1 ng-click="pings.press()">asdf</h1>
  </div>
</html>

Javascript is here:

angular.module('coolApp', [])

.controller('PingsCtrl', function() {
  var vm = this;

  vm.press = function() {alert(123)};
})

What's wrong and how do I fix this?

Share Improve this question asked Dec 21, 2015 at 19:45 thank_youthank_you 11.1k19 gold badges106 silver badges194 bronze badges 13
  • 1 Consider putting mon functions in a factory service. They are singletons and automatically loaded only once. See docs.angularjs/guide/services#creating-services – georgeawg Commented Dec 21, 2015 at 20:05
  • 1 Just one page. Understand I'm using Rails framework which injects the snippets of html. I excluded that piece of information because it has zero bearing on the issue at hand. – thank_you Commented Dec 24, 2015 at 0:29
  • 1 @user648026 I thought of that too. The more I think about it, that is the best and only way. Was just hoping to see if there was an alternate means via conditionally applying ng-controller. – thank_you Commented Dec 28, 2015 at 22:22
  • 1 why not just use a dummy div that will contain either the first or second page? I found a link to actually instantiate a controller based on a condition but the problem here is that the scope of your pings controller is restricted to that div and it's children so your second page will get pings as undefined. In any case here's the link stackoverflow./questions/20866954/… – martskins Commented Dec 29, 2015 at 20:20
  • 1 What is it that you're trying to achieve exactly ? If you go from first page to second page with a full page refresh then you loose all JS context angular or otherwise. – Arkantos Commented Dec 31, 2015 at 14:39
 |  Show 8 more ments

3 Answers 3

Reset to default 7

Just use a service. It's really the intended structure for having mon data and functionality between pages.

Part of the problem with what you were attempting is, whether or not you manage to preserve the controller, Angular has its own management that won't follow you with that, and will be refreshing ponents without you. You'll run into things like a $scope that doesn't actually match the page you're looking at, and it ends up causing more problems than it's worth.

I do have a solution but I also echo other people's concerns about the approach. You may want to have a global controller that you drop on the body for things that can happen anywhere and in most of the other controllers and just call through that. Eg

<body ng-controller="GlobalCtrl as gc">
    <h1 ng-click="gc.pingPress()"></h1>
</body>

Anyway here is what I came up with.

<div ng-if="pings">
    <h1 ng-click="pings.press()">asdf</h1>
</div>
<div ng-if="!pings">
    <div ng-controller="PingsCtrl as pings">
        <h1 ng-click="pings.press()">asdf</h1>
    </div>
</div>

This will work if it is dropped inside or outside of an existing PingsCtrl.

Here is a plunker.

https://plnkr.co/edit/4x0kSazcg0g0BsqPKN9C?p=preview

Please, check my solution to see how to share data between controllers

var app = angular.module('myApp', []);

app.controller("aCtrl", function ($scope, PingList) {
  $scope.addPing = function() {
    PingList.add('Ping A');
  };
});

app.controller("bCtrl", function ($scope, PingList) {
  $scope.addPing = function() {
    PingList.add('Ping B');
  };
});

app.factory('PingList', function () {
  var pings = ['Ping1', 'Ping2'];

  return {
    add: function(ping) {
      pings.push(ping);
    },
    get: function () {
      return pings;
    }
  };
});

app.directive('pingList', function(PingList) {
  return {
    restrict: 'EA',
    link: function($scope) {
      $scope.pings = PingList.get();
      $scope.press = function(ping) {
        alert(ping);
      }
    },
    template: '<ul><li ng-repeat="ping in pings" ng-click="press(ping)">{{ping}}</li></ul>'
  };
});
a, li {
  cursor: pointer;
}

a {
  color: blue;
  text-decoration: underline;
}
<script src="https://ajax.googleapis./ajax/libs/angularjs/1.0.8/angular.min.js"></script>

<div ng-app="myApp">
  <div ng-controller="aCtrl" style="float: left">
    <a ng-click="addPing()">click to add A ping</a>
    <ping-list></ping-list>
  </div>
  <div ng-controller="bCtrl" style="float: right">
    <a ng-click="addPing()">click to add B ping</a>
    <ping-list></ping-list>
  </div>
  <div style="clear: both"></div>
</div>

发布评论

评论列表(0)

  1. 暂无评论