Reputation: 289
So, Right now I'm practicing JS/OOP/Angular via creating some kind of light-text-browser-game :) Got stuck in the simple situation (like always). I simplify my code a bit, here it is: https://jsfiddle.net/gjgjc3fx/1/. So I've just created a 'class' Hero using factory:
angular.module('myGame', [])
.factory('Hero', function() {
function Hero(name, damage) {
this.name = name;
this.damage = damage;
}
Hero.prototype = {
talk : function() {
alert('Hi, my name is: ' + this.name + ', my current damage is: ' + this.damage);
},
addDamage : function(damage) {
this.damage += damage;
console.log(this.damage);
}
}
return Hero;
})
and then use it in controller:
.controller('myGameCtrl', function($scope, Hero) {
var am = new Hero('AntiMage', 70);
$scope.currentDamage = am.damage;
$scope.hi = function() {
am.talk();
}
$scope.add50Dmg = function() {
am.addDamage(50);
}
})
HTML:
<div ng-app='myGame' ng-controller='myGameCtrl'>
<div>{{currentDamage}}</div>
<button ng-click='add50Dmg()'>Add 50 damage</button>
<div ng-click='hi()'>Hi</div>
</div>
The question is - what am I suppose to fix if I wanna see in the <div>{{currentDamage}}</div>
changing damage in real time? I mean if I click on button it will add 50 damage and I can see change in alert's window, but the <div>{{currentDamage}}</div>
stay the same (70) all the way. Any help and advices will be great.
Upvotes: 0
Views: 1605
Reputation: 23793
So there's already two answers and yes, they'll be working.
But I'd like to show you how to make a reactive version of it (like you'd do with Angular2 for example).
First of all, here's a working Plunkr of your code.
EDIT : I updated the Plunkr to show you how to use component
instead of controller
and I created multiple instance of the game so you can see that it's well synchronized ;) !
Explanations :
Define the app
let app = angular.module('myGame', []);
Define Heroes
factory
app.factory('Heroes', function() {
// ---------------------------------------------
// ---------------- observable -----------------
// ---------------------------------------------
let heroesFactoryObserver;
let heroesFactory$ = new Rx.Observable.create((observer) => {
heroesFactoryObserver = observer;
})
.share();
// data to subscribe from controller
let data = {};
// ---------------------------------------------
// ------------------- Hero --------------------
// ---------------------------------------------
let heroId = 0;
let Hero = function(name, damage) {
this.id = heroId++;
this.name = name;
this.damage = damage;
this.hi = () => {
alert('Hi, my name is: ' + this.name + ', my current damage is: ' + this.damage);
};
// default damage : 10
this.addDamage = (damage = 10) => {
this.damage += damage;
heroesFactoryObserver.next(data);
};
};
// ---------------------------------------------
// -------------- Data to share ----------------
// ---------------------------------------------
data = {
// the observable to subscribe to data change
heroesFactory$,
// whenever you need to force update, for example when
// the app is loaded and you want to get data for the first time
update: () => heroesFactoryObserver.next(data),
// your array of heroes
heroes: [],
// create a new hero and add him to heroes array
createHero: (name, damage) => data.heroes.push(new Hero(name, damage))
};
return data;
});
Define the controller
app.controller('myGameCtrl', function($scope, Heroes) {
// whenever a heroe his updated
Heroes.heroesFactory$.subscribe(h => {
$scope.heroes = h.heroes;
});
// load data once by asking Heroes to trigger a change
// so that every other component can update too
Heroes.update();
});
It's more verbose for sure. But has it forces you to use setters (so you can trigger observer.next()
), you can use that as hooks and do what you want here. Plus, instead of using angular watch and have the logic within a watch (that you'll need to duplicate for each component where you want to watch the data), you have one source by factory.
And the best setup I've ever tried is Redux + RxJs. (and I've read that it's possible to use ngrx with AngularJs, not only Angular2).
Upvotes: 1
Reputation: 119
More simple
angular.module('myGame', [])
.controller('myGameCtrl', function($scope) {
var vm = $scope ;
vm.currentdamage = 20;
// currentdamage = 20;
vm.add50Dmg=function(){
vm.currentdamage = vm.currentdamage +50;
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='myGame' ng-controller='myGameCtrl'>
<div>tst {{currentdamage}}</div>
<button ng-click='add50Dmg()'>Add 50 damage</button>
<div ng-click='hi()'>Hi</div>
</div>
Upvotes: 0
Reputation: 2043
your Updated fiddle
The problem is you are not updating $scope.currentDemage
. For updating $scope.currentDemage
you have to get the valuee from your Hero
Factory.
Add getDamage
function in your factory like
Hero.prototype = {
talk : function() {
alert('Hi, my name is: ' + this.name + ', my current damage is: ' + this.damage);
},
addDamage : function(damage) {
this.damage += damage;
console.log(this.damage);
},
/* getDamage function */
getDamage : function(){
return this.damage;
}
}
Assign your factory instance to $scope
variable in ngController like
$scope.myService = am;
// watch getDamage() function for binding new Value.
$scope.$watch('myService.getDamage()',function(newvalue){
$scope.currentDamage = newvalue;
})
Upvotes: 1