Reputation: 2004
I'm probably getting confused with mvc and angularjs and trying to set a boolean to control a scope variable to hide a div.
I have a list html page that includes this:
<tbody>{{isAuthorised}}
<tr ng-repeat="calendarEvent in items" id="event_{{calendarEvent.Id}}">
<td><strong>{{calendarEvent.EventTitle}}</strong><br/>{{calendarEvent.EventDescription}}</td>
<td>{{calendarEvent.EventDate | date:mediumDate}}</td>
<td><img src="{{calendarEvent.ThumbnailUrl}}" alt="" width="100" /></td>
<td>
<div ng-show="isAuthorised">
<a href="#/edit/{{calendarEvent.Id}}"><i class="glyphicon glyphicon-edit"></i></a>
<a ng-click="delete()"><i class="glyphicon glyphicon-remove"></i></a>
</div>
</td>
</tr>
</tbody>
I'm outputting the value currently to try to figure out what is going on. So if I hit this page with setting the value the div shows my edit and delete buttons which I don't want. The value of the scope variable displays as {}.
I have this app.js code:
var ListCtrl = function ($scope, $location, CalendarEvent, SharedService) {
** lots of stuff removed as irrelevant **
$scope.isAuthorised = SharedService.get();
};
My login controller via a separate html content section that is setting the value (in the shared service)
var LoginCtrl = function ($scope, $location, $http, SharedService) {
$scope.login = function () {
$http.get("/AuthorisedUser/IsValidUser/" + $scope.item.ValidEmailAddress + "/")
.success(function (result) {
var isAuthorised = result.toLowerCase();
if (isAuthorised) {
SharedService.set(isAuthorised);
$location.path('/');
} else {
alert('you do not have the power!');
}
})
.error(function() {
alert('Email could not be Validated at this time');
});
}
};
the result is an MVC method returning a bool type. I thought maybe I needed to convert the bool to lower case because javascript would like it better, but maybe that's doing some implicit conversion to a string or something?! I'm not sure what I need to change in my list html to properly show that div only when the value is true. I'm coming from a .NET background with limited AngularJS understanding.
The value seems to being set, because if I put in a valid email address I'm seeing
true
in the html page where the scope variable is.
It seemed to work once in Chrome - but now that's not working, and just showing the stuff that should be hidden.
Sorry forgot to include the shared service:
EventsCalendarApp.factory('SharedService', function() {
var savedData = {}
function set(data) {
savedData = data;
}
function get() {
return savedData;
}
return {
set: set,
get: get
}
});
Upvotes: 1
Views: 182
Reputation: 52867
I think everything would be simplified in your controller, service, and UI if your service dealt with object references rather than a Boolean value (which is a primitive).
Your service:
EventsCalendarApp.factory('SharedService', function() {
var savedData = { isAuthorised: false }
function set(data) {
// overwrites savedData properties with data's properties,
// but preserves the reference
angular.copy(data, savedData);
}
function setAuthorised(authorised) {
savedData.isAuthorised = authorised;
}
function get() {
return savedData;
}
return {
set: set,
get: get,
setAuthorised: setAuthorised
}
});
Your Login controller:
var LoginCtrl = function ($scope, $location, $http, SharedService) {
// helper function to determine if str contains 'true'
function parseBoolean(str) {
return /^true$/i.test(str);
}
$scope.login = function () {
$http.get("/AuthorisedUser/IsValidUser/" + $scope.item.ValidEmailAddress + "/")
.success(function (result) {
var isAuthorised = parseBoolean(result);
if (isAuthorised) {
SharedService.set({ isAuthorised: isAuthorised });
// OR
SharedService.setAuthorised(isAuthorised);
$location.path('/');
} else {
alert('you do not have the power!');
}
})
.error(function() {
alert('Email could not be Validated at this time');
});
}
};
Your List Controller:
var ListCtrl = function ($scope, $location, CalendarEvent, SharedService) {
** lots of stuff removed as irrelevant **
$scope.savedData = SharedService.get();
};
HTML:
<tbody>{{savedData.isAuthorised}}
<tr ng-repeat="calendarEvent in items" id="event_{{calendarEvent.Id}}">
<td><strong>{{calendarEvent.EventTitle}}</strong><br/>{{calendarEvent.EventDescription}}</td>
<td>{{calendarEvent.EventDate | date:mediumDate}}</td>
<td><img ng-src="{{calendarEvent.ThumbnailUrl}}" alt="" width="100" /></td>
<td>
<div ng-show="savedData.isAuthorised">
<a href="#/edit/{{calendarEvent.Id}}"><i class="glyphicon glyphicon-edit"></i></a>
<a ng-click="delete()"><i class="glyphicon glyphicon-remove"></i></a>
</div>
</td>
</tr>
</tbody>
When you use object references, then any changes to the reference from within your service is automatically propagated to the views; as do any changes to the reference that happen inside a controller. There is no real magic behind this - they are automatically updated because they are the same reference. In contrast, when you use primitives, then a copy of the value is passed around, and it becomes more challenging to keep them all in synch.
NOTE: on an unrelated note, you should use ng-src for image URLs that are binding expressions. This ensures that the image URL is only downloaded by the browser after the expression is evaluated and rendered.
Upvotes: 1
Reputation: 2004
So the answer was to update the ListCtrl to have this logic:
var ListCtrl = function ($scope, $location, CalendarEvent, SharedService) {
var authorised = SharedService.get();
if (authorised != "true")
$scope.isAuthorised = false;
else
$scope.isAuthorised = SharedService.get();
};
It now seems to be working! I'm still confused about the handling of booleans in javascript as I seem to have a mix of boolean and string going on in the various methods.
Upvotes: 0
Reputation: 55443
var LoginCtrl = function ($scope, $location, $http, SharedService) {
$scope.login = function () {
$http.get("/AuthorisedUser/IsValidUser/" + $scope.item.ValidEmailAddress + "/")
.success(function (result) {
$scope.isAuthorised = result.toLowerCase();
})
.error(function() {
alert('Email could not be Validated at this time');
});
}
};
Keep one thing in mind you $scope works as a bridge between controller and view. if your controller update $scope, your view gets changed. Don't use sharedservice here. its useless for what you want to do. try my above snippet.
Upvotes: 0