Reputation: 739
I am new in this field and want to write a app, now I meet some problems. Here is a simple version of my code, what I want is the API only show signUp
first. After I press signUp
and press submit
the button shown should be only signout
I think my way is not all right, because after I change the value in service, another controller can't update its value. Could you tell me that?
please use this.logged
if possible, thanks!
The process is not necessary to be same to my title. OK if it can implement my function.
https://plnkr.co/edit/1ptaVzmD7EwPZ6dU23gR?p=preview
(function(){
angular.module('myApp',['myApp.dashboard','myApp.value','myApp.signUp']);
})();
(function(){
angular.module('myApp.dashboard',[]);
})();
(function(){
angular.module('myApp.value',[]);
})();
(function(){
angular.module('myApp.signUp',[]);
})();
(function(){
'use strict';
angular.module('myApp.dashboard').controller('mainControl',mainControl);
mainControl.$inject = ['whichToShow'];
function mainControl(whichToShow){
this.logged=whichToShow.getVar();
alert(this.logged);
}
})();
(function(){
'use strict';
angular.module('myApp.value').factory('whichToShow',function(){
alert("running2");
var logged=false;
return {
getVar: function(){
return logged;
},
setVar: function(value){
logged=value;
}
};
});
})();
(function(){
'use strict';
angular.module('myApp.signUp').controller('signUpControl',signUpControl);
signUpControl.$inject = ['whichToShow'];
function signUpControl(whichToShow){
alert("haha");
this.logIn=function(){
whichToShow.setVar(true);
alert("running set!");
};
};
})();
partial html:
<body ng-controller="mainControl as mc">
<div>
<div ng-hide="mc.logged">
<button type="button" class="btn" data-toggle="modal" data-target=".signUp">Sign Up</button>
</div>
<div ng-show="mc.logged">
<button>Sign Out</button>
</div>
</div>
<div class="signUp modal fade" id="signUp" ng-controller='signUpControl as sc'>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">sigh up</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>
</div>
<div class="modal-body">
<form id="signUpForm" name="signUpForm" ng-submit="sc.logIn()">
<label for="email">
<span>email:</span>
<input type="email" name="email">
</label>
<button class="submit" id="signUpSubmit" type="submit" value="signUp">submit</button>
</form>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
</body>
Upvotes: 1
Views: 288
Reputation: 22323
You are still trying to set the value of primitives here, rather than object properties. In JavaScript, primitives are passed byValue, not byReference, so whichToShow.getVar();
is returning true
or false
rather than returning a reference to logged
. Therefore, you won't see changes to logged
unless you call .getVar()
again, to get the new value. This is why most answers you have seen so far have had some form of $watch
, $broadcast
, or similar, to alert your mc
that it should ask again for the logged
variable's current value.
If you want to avoid using a $watch
, you should use an object instead of a primitive. by using an object, you can pass the object byReference, which will allow angular to see the changes to the properties wherever there is a reference set.
In your factory, return an object:
(function() {
'use strict';
angular.module('myApp.value').factory('whichToShow', function() {
alert("running2");
var status = {
logged: false
};
var logged = false;
return {
getVar: function() {
return status;
},
setVar: function(value) {
status.logged = value;
}
};
});
})();
In mainControl, use a reference to this object:
(function() {
'use strict';
angular.module('myApp.value').factory('whichToShow', function() {
alert("running2");
var status = {
logged: false
};
return {
getVar: function() {
return status;
},
setVar: function(value) {
status.logged = value;
}
};
});
})();
And finally, use the object property in the HTML:
<div ng-hide="mc.status.logged">
...
<div ng-show="mc.status.logged">
...
https://plnkr.co/edit/Pindt2LYxDxyk8C5Axp1?p=preview
I might even go one step further and just return the object directly by the service, and skip the getVar
and setVar
functions.
Upvotes: 1
Reputation: 3130
You need watch for the changes on the logged value from the service.
That is all you need to do.
(function() {
angular.module('myApp', ['myApp.dashboard', 'myApp.value', 'myApp.signUp']);
})();
(function() {
angular.module('myApp.dashboard', []);
})();
(function() {
angular.module('myApp.value', []);
})();
(function() {
angular.module('myApp.signUp', []);
})();
(function() {
'use strict';
angular.module('myApp.dashboard').controller('mainControl', mainControl);
mainControl.$inject = ['$scope', 'whichToShow'];
function mainControl($scope, whichToShow) {
$scope.$watch(() => whichToShow.getVar(), (newValue, oldValue) => this.logged = newValue)
}
})();
(function() {
'use strict';
angular.module('myApp.value').factory('whichToShow', function() {
var logged = false;
var service = {};
return {
getVar: function() {
return logged;
},
setVar: function(value) {
logged = value;
}
}
});
})();
(function() {
'use strict';
angular.module('myApp.signUp').controller('signUpControl', signUpControl);
signUpControl.$inject = ['whichToShow'];
function signUpControl(whichToShow) {
this.logIn = function() {
whichToShow.setVar(true);
};
};
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div ng-app="myApp">
<div ng-controller="mainControl as mc">
<div>
<div ng-hide="mc.logged">
<button type="button" class="btn" data-toggle="modal" data-target=".signUp">Sign Up</button>
</div>
<div ng-show="mc.logged">
<button>Sign Out</button>
</div>
</div>
<div class="signUp modal fade" id="signUp" ng-controller='signUpControl as sc'>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">sigh up</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>
</div>
<div class="modal-body">
<form id="signUpForm" name="signUpForm" ng-submit="sc.logIn()">
<label for="email">
<span>email:</span>
<input type="email" name="email">
</label>
<button class="submit" id="signUpSubmit" type="submit" value="signUp">submit</button>
</form>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
</div>
</div>
Working solution on Codepen
Upvotes: 1
Reputation: 2105
Basically you are setting values in factory object after user clicks on submit but that doesn't reflect in UI as you have not updated the scope object this.logged
.So to tell main controller fromsign up controller that change the this.logged $scope
value we can use $emit
or $broadcast
Apart from $watch
approach you can even use $broadcast
to achieve this.
Working DEMO
Just add this below code in your JS file controllers
signUpControl
(function(){
'use strict';
angular.module('myApp.signUp').controller('signUpControl',signUpControl);
signUpControl.$inject = ['whichToShow','$rootScope'];
function signUpControl(whichToShow,$rootScope){
alert("haha");
this.logIn=function(){
whichToShow.setVar(true);
$rootScope.$broadcast('login');//broadcasting that user has logged in
//alert("running set!");
};
};
})
mainControl
(function(){
'use strict';
angular.module('myApp.dashboard').controller('mainControl',mainControl);
mainControl.$inject = ['whichToShow','$rootScope'];
function mainControl(whichToShow,$rootScope){
var mc = this;
mc.main ={};
mc.main.logged=whichToShow.getVar();
alert(mc.main.logged);
// below code will listen to the broadcast and do the necessary process..
$rootScope.$on('login',function(event,args){
mc.main.logged=whichToShow.getVar();
});
}
})
Upvotes: 1
Reputation: 542
You can put some variable globally or in your rootcontroller,lets says isLoggedIn
now with one service you can set this variable on signingIn
and use it like this {
}<span data-ng-if="!isLoggedIn">Sign In</span>
<span data-ng-if="isLoggedIn">Sign Out</span>
Upvotes: 0