I am very new to AngularJS. I have to make what seems like a very small change to our website, but it's stumping me.
- We have a boolean value in our Django user model, let's call it user.myValue
- On page load, display text "A" if that boolean is True, and text "B" if it is False
- In that message text, we have a link element that fires an AngularJS function to open a modal.
- In the modal, there are two buttons. Clicking them will toggle the boolean value by calling a Django REST endpoint.
- If the call to that REST endpoint is successful, the value in the database will be updated. (Either way, we close the modal.)
- On successful update of the database, I now want the message on the main page to be updated to show the correct message based on the new value.
I've managed to get everything up to the last step. I've played with a lot of potential solutions and nothing is quite working. For the element holding the message text,
- Binding would be ideal because then I can just use
$scope.apply()
to update the element, but because it's a boolean using ng-bind
isn't great: I don't want to just show the user "true" or "false".
- ng-if is ugly because on page load it displays both messages for a split second and then removes one. I also can't figure out how to get it to re-run the "if" condition when we've had a successful database update.
- I've played with creating a directive, but that also doesn't seem right.
ng-model="user.myValue" ng-value="true"
isn't useful because it doesn't conditionally show the message...
Here's my code so far.
Template:
<div ng-controller="myCtrl">
<div id="modal-my-value-toggle" class="modal">
<a ng-click="myValueToggle('false')">No</a>
<a ng-click="myValueToggle('true')">Yes</a>
</div>
{% if user.myValue %}
<div name="myValueTrue">
Message A: Your value is Yes. <a ng-click="openModal()">click here to change your value</a>
</div>
{% else %}
<div name="myValueFalse">
Message B: Your value is No. <a ng-click="openModal()">click here to change your value</a>
</div>
{% endif %}
</div>
Controller:
function myCtrl ($scope, $http, Notification) {
$scope.username = context.targetUsername;
$scope.openModal = function() {
var $myModal = $('div').find('#modal-my-value-toggle');
$myModal.modal({
keyboard: false,
backdrop: "static"
});
$myModal.modal('show');
};
$scope.myValueToggle = function(userProvidedValue) {
// hide the modal
var $myModal = $('div').find('#modal-my-value-toggle');
$myModal.modal('hide');
if (userProvidedValue === 'true') {
var success = "Your value is now Yes";
} else {
var success = "Your value is now No";
}
// ping the api to set flag to true
$http({
method: 'GET',
url: '/api/user/' + $scope.username + '/myValue/?myValue=' + userProvidedValue,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function(response) {
Notification.success(success);
}, function(response) {
Notification.error("There was an error.");
});
};
}
Some other stuff I tried...
This is based on this https://coderwall.com/p/ybbopq/use-ng-value-for-ng-model-with-boolean-values It just displays both messages and isn't really what I want. It's meant to provide a radio input that you can switch between to update the value in $scope.
<div name="myValue_true" ng-model="user.myValue" ng-value="true">
Message A: Your value is Yes. <a ng-click="openModal()">click here to change your value</a>
</div>
<div name="myValue_false" ng-model="user.myValue" ng-value="false">
Message B: Your value is No. <a ng-click="openModal()">click here to change your value</a>
</div>
This one is just a different way of deciding which message to display on initial page load. It flashes both messages and then removes one.
<div ng-if="user.myValue">
Message A: Your value is Yes. <a ng-click="openModal()">click here to change your value</a>
</div>
<div ng-if="!user.myValue">
Message B: Your value is No. <a ng-click="openModal()">click here to change your value</a>
</div>
I also tried this janky thing in the controller (didn't work):
function myCtrl ($scope, $http, Notification) {
$scope.username = context.targetUsername;
$scope.openModal = function() {
var $myModal = $('div').find('#modal-my-value-toggle');
$myModal.modal({
keyboard: false,
backdrop: "static"
});
$myModal.modal('show');
};
$scope.myValueToggle = function(userProvidedValue) {
// hide the modal
var $myModal = $('div').find('#modal-my-value-toggle');
$myModal.modal('hide');
var message_ids = {
'yes': 'myValue_true',
'no': 'myValue_false'
}
if (userProvidedValue === 'true') {
var success = "Your value is now Yes";
var show_message = message_ids['yes']
var hide_message = message_ids['no']
} else {
var success = "Your value is now No";
var show_message = message_ids['no']
var hide_message = message_ids['yes']
}
// ping the api to set flag to true
$http({
method: 'GET',
url: '/api/user/' + $scope.username + '/myValue/?myValue=' + userProvidedValue,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function(response) {
$('div').find('#' + show_message).show();
$('div').find('#' + hide_message).hide();
Notification.success(success);
}, function(response) {
Notification.error("There was an error.");
});
};
}
Am I going about this completely the wrong way? Am I supposed to be making a directive out of the message element? Or something else? Any help would be greatly appreciated. Thank you!
See Question&Answers more detail:
os