I am trying to show different divs depending the response I get from an http request.
$scope.firstStep = true;
$scope.secondStep = false;
$scope.thirdStep = false;
$http({
method: 'GET',
url: '/api-web/ec/cadastro/recuperar-acesso',
data: {
filiacao: $scope.currentFiliacao,
cnpj: $scope.currentCNPJ
},
headers: {'Content-Type': 'application/json'}
}).then(function(res){
$scope.firstStep === false;
if (res.data.code === -1) {
$timeout( function (){
$scope.secondStep === true; //here is the bug, it dont change to true
console.log("second", $scope.secondStep);
}, 3000)
}
})
I tried several things, like $apply(), _defer, switch from === to =
... and I have no idea why its happening.
Any ideas ?
Doesn't this work?
$timeout( function (){
$scope.secondStep = true;
$scope.apply();
console.log("second", $scope.secondStep);
}, 3000)
Related
I have to upload some files, for each file api is being called. Now if user want to cancel the upload using cancel button in a dialog box.
Please suggest how to reach to this solution.
I am using react and javascript for the file upload.
File upload component is in a different component.
api call is at utils page as shown
_bulkUpload: function(query, rType,sucessCount,failureCount,name) {
Api._callAPI(Url.BULK_UPLOAD, 'POST', query, (type, dt) => {
if(type=="success"){
let data = dt.res_data;
dispatcher.dispatch({
type:'DRAFT_BULK_UPLOAD',
response: sucessCount,
name: name,
});
dispatcher.dispatch({
type:'SNACKBAR',
str: dt.res_str,
toastType:0,
});
/*dispatcher.dispatch({
type:'DRAFT_BULK_UPLOAD',
response: count
});*/
} else {
dispatcher.dispatch({
type:'BULK_FAILED',
response: failureCount,
name: name
});
dispatcher.dispatch({
type: 'SNACKBAR',
str: Api._showErrorMsg(dt.status,dt.responseJSON||'')
});
}
dispatcher.dispatch({
type: 'LOADER',
loader: false
});
}, rType);
},
Api._callAPI function is calling a component as shown.
_callAPI : function(url,method,data,target,cType){
if(data && data.org_id && ([Url.PRELOGIN_CREATE_SUPER_USER,Url.PRELOGIN_CREATE_USER].indexOf(url) !== -1)){
// data.org_id = this._getKey('org_id');
}
else{
if([Url.SSO_CHECK,Url.PRELOGIN_FETCH,Url.LOGIN,Url.PRELOGIN_SEND_OTP,Url.PRELOGIN_VERIFY_OTP,Url.PRELOGIN_VERIFY_EMAIL,Url.COUNTRYCODE_TYPEAHEAD].indexOf(url) === -1)
if(!this._getKey('id') || !this._getKey('value')){
return false;
}
}
$.ajax({
url: BASEURL+url,
method: method,
data: data,
processData: (cType == 'multipart/form-data' ? false :true),
dataType: (cType == 'multipart/form-data' ? '' :'json'),
beforeSend: (xhr) => {
if(this._getKey('id') && this._getKey('value')){
xhr.setRequestHeader('XYZ-ID',this._getKey('id'));
xhr.setRequestHeader('XYZ-VALUE',this._getKey('value'));
if (this._getKey('viewType') == 'Privileged') {
xhr.setRequestHeader('XYZ-HASROLE','Y');
}
else{
xhr.setRequestHeader('XYZ-HASROLE','N');
}
xhr.setRequestHeader('x-csrfvalue',Math.random());
if (this._getKey('delegation_bit') === 'true') {
xhr.setRequestHeader('XYZ-DELEGATOR', this._getKey('delegator_id'));
xhr.setRequestHeader('XYZ-DELEGATION-ID', this._getKey('delegation_id'));
}
}
},
contentType: cType ? false : "application/x-www-form-urlencoded",
success: (data,textStatus, jqXHR) => {
if(jqXHR.getResponseHeader('XYZ-ID')){
this._setKey('id',jqXHR.getResponseHeader('XYZ-ID'));
}
if(jqXHR.getResponseHeader('XYZ-VALUE')){
this._setKey('value',jqXHR.getResponseHeader('XYZ-VALUE'));
}
/*dispatcher.dispatch({
type: 'LOADER',
loader: false
});*/
target('success',data);
},
error: (jqXhr,textStatus,error) => {
dispatcher.dispatch({
type: 'LOADER',
loader: false
});
if(jqXhr.status == 401){
this._clearStorage();
// try {
// sessionStorage.setItem('lastVisitedPage', window.location.hash.split("#")[1].split("?")[0]);
// } catch (ex) {
// console.log("Does not support CRUD with Storage");
// }
this._redirectToLogin();
} else{
target('error',jqXhr,textStatus,error);
}
}
});
},
File Upload and api call part
_handleFileUpload(){
let {failedBillCounter,statusArr} = this.state;
let sucessCount = 0;
let failureCount = 0;
var count=failedBillCounter;
let newFiles = document.getElementById('myFile').files;
let arr = [];
if(newFiles.length > 25){
UserInfoStores.showToast(Errors.MAX_NO_OF_FILE);
document.getElementById('myFile').value = "";
return false;
}
this.setState({fileCount:newFiles.length})
document.getElementById('draftBillBar').style.display = 'block';
//let newData = new FormData();
for(let i=0;i< newFiles.length;i++){
let newData = new FormData();
let files = [];
let txn_attachments = [];
if(newFiles[i].size/(1024*1024) > 15){
count=count+1;
statusArr.push({name:newFiles[i].name,type:'failed'})
this.setState({
statusArr,
failedBillCounter:count,
failCounterFlag:true,
},()=>this.progressBar());
}
else{
newData.append('files-'+i,newFiles[i],newFiles[i].name);
txn_attachments.push('files-'+i);
newData.append('txn_attachments', txn_attachments);
newData.append('source', 'web');
newData.txn_attachments = JSON.stringify(txn_attachments);
DraftAction.draftBulkUpload(newData,'multipart/form-data', sucessCount,failureCount,newFiles[i].name)
}
}
}
you must make a function to cancel the upload make a global variable for your ajaxCall
var ajaxCall;
_callAPI : function(...) {
...
...
ajaxCall = $.ajax({ ... });
}
// make a function to call when user click the cancel upload button
_cancelAjaxCall : function() {
ajaxCall.abort();
}
hope it works...
Currently grecaptcha.execute is being executed on page load as in the first JS example below. If reCAPTCHA challenge is triggered this happens when the page has loaded. Ideally this would happen when the form submit button is clicked instead.
So I've tried this by moving this into the submit event (second JS example) and put the axios function into a promise. It's submitting before grecaptcha.execute has finished executing.
What is it that I'm not understanding here?
My first experience with promises so am I not understanding how promises work? Is that not the best solution for this problem? Is is something else entirely?
HTML
<head>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" defer></script>
</head>
JS
const form = document.querySelector('#subscribe');
let recaptchaToken;
const recaptchaExecute = (token) => {
recaptchaToken = token;
};
const onloadCallback = () => {
grecaptcha.render('recaptcha', {
'sitekey': 'abcexamplesitekey',
'callback': recaptchaExecute,
'size': 'invisible',
});
grecaptcha.execute();
};
form.addEventListener('submit', (e) => {
e.preventDefault();
const formResponse = document.querySelector('.js-form__error-message');
axios({
method: 'POST',
url: '/actions/newsletter/verifyRecaptcha',
data: qs.stringify({
recaptcha: recaptchaToken,
[window.csrfTokenName]: window.csrfTokenValue,
}),
config: {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
},
}).then((data) => {
if (data && data.data.success) {
formResponse.innerHTML = '';
form.submit();
} else {
formResponse.innerHTML = 'Form submission failed, please try again';
}
});
}
JS
const onloadCallback = () => {
grecaptcha.render('recaptcha', {
'sitekey': 'abcexamplesitekey',
'callback': recaptchaExecute,
'size': 'invisible',
});
};
form.addEventListener('submit', (e) => {
e.preventDefault();
const formResponse = document.querySelector('.js-form__error-message');
grecaptcha.execute().then(axios({
method: 'POST',
url: '/actions/newsletter/verifyRecaptcha',
data: qs.stringify({
recaptcha: recaptchaToken,
[window.csrfTokenName]: window.csrfTokenValue,
}),
config: {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
},
})).then((data) => {
if (data && data.data.success) {
formResponse.innerHTML = '';
form.submit();
} else {
formResponse.innerHTML = 'Form submission failed, please try again';
}
});
}
I'm using a web service, as I wanted a method that I could use in all pages.
Special attention to the fact you need to return false; and when the ajax request returns, do your post back.
<script type="text/javascript">
function CheckCaptcha()
{
grecaptcha.ready(function () {
grecaptcha.execute('<%#RecaptchaSiteKey%>', { action: 'homepage' }).then(function (token) {
$.ajax({
type: "POST",
url: "../WebServices/Captcha.asmx/CaptchaVerify",
data: JSON.stringify({ 'captchaToken' : token }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
__doPostBack('<%= RegisterButton.UniqueID%>', '');
//console.log('Passed the token successfully');
},
failure: function (response) {
//alert(response.d);
}
});
});
});
return false;
}
</script>
The way I resolved this is by changing the submit button into a dumb button, and handling everything in a js method:
#Html.HiddenFor(model => model.ReCaptchaToken);
<input type="button"
value="Submit"
onclick="onSubmit()"
/>
Then() method waits for the token, puts it in a hidden field, and only then manually submits the form:
<script>
if (typeof grecaptcha == 'object') { //undefined behind the great firewall
grecaptcha.execute('#Config.ReCaptchaSiteKey', { action: 'register' }).then(function (token) {
window.document.getElementById('ReCaptchaToken').value = token;
$('form').submit();
});
} else {
window.document.getElementById('ReCaptchaToken').value = -1;
$('form').submit();
}
</script>
Note: #Html.HiddenFor is MVC - you might not use that.
$('form') is JQuery - you don't necessarily need that - can use getElementById as well.
I have created a simple dashboard with some data as a tryout in Angular. With PHP I get some weather data, news via Google News and 10 tweets about a keyword.
With the $interval I refresh the dashboard every 10 seconds, but I want a countdown from 10 to 0, which starts over and over when the interval is triggered.
Can somebody help me to achieve this?
Current code as submitbutton and $interval trigger:
$scope.formSubmit = function(){
$scope.getResults();
if($scope.interval){
intervalController();
}
}
function intervalController(){
$interval($scope.getResults, 10000);
}
$scope.getResults = function(){
if($scope.city){
$http({
method: 'POST',
url: 'server.php',
data: {city : $scope.city}
}).then(function successCallback(response){
console.log(response.data);
//some data processing here
}, function errorCallback(response){
})
}
}
$scope.initialCountDownValue = 10;
$scope.countDownValue = $scope.initialCountDownValue;
var intervalCanceller = null;
$scope.formSubmit = function(){
$scope.getResults();
if($scope.interval){
intervalController();
}
}
function decrementCountdown() {
$scope.countDownValue -= 1;
if ( $scope.countDownValue === 0) {
$scope.getResults();
$scope.countDownValue = $scope.initialCountDownValue;
}
}
function intervalController(){
intervalCanceller = $interval(decrementCountdown, 1000);
}
$scope.getResults = function(){
if($scope.city){
$http({
method: 'POST',
url: 'server.php',
data: {city : $scope.city}
}).then(function successCallback(response){
console.log(response.data);
//some data processing here
}, function errorCallback(response){
})
}
}
in $scope.countDownValue you have your countdown value to display to the user.
One additional point.
Do not to forget to unsubscribe your $interval on the scope destruction. Or you will have an interval living for ever for nothing.
Here is the way to destroy your interval properly :
$scope.$on('$destroy', function() {
if (intervalCanceller) {
$interval.cancel(intervalCanceller);
}
});
I have a form through which i am adding the data. Same is the case for data update. I populate form by getting data against a particular id via $http post. I have changed the scope variables but not getting modified values. Here are my efforts :
<input type="hidden" name="form_type" ng-model="formData.formType" ng-init="formData.formType = submit_button" value="{{submit_button}}"/>
<input type="hidden" name="student_id" ng-model="formData.studentId" ng-init="formData.studentId = student_id" value="{{student_id}}"/>
$scope.Edit = function (id) {
$http({
method: 'POST',
url: 'process.php',
data: $.param({action: 'fetch', id: id}),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function (response) {
if (!response.success) {
alert("something went wronge");
return false;
} else {
$scope.formData = response.data;
$scope.student_id = response.data.id;
$scope.submit_button = 'Update';
$scope.$apply();
}
});
};
This is the way of the safe apply in the scope.
$scope.safeApply = function(fn) {
var phase = this.$root.$$phase;
if(phase == '$apply' || phase == '$digest') {
if(fn && (typeof(fn) === 'function')) {
fn();
}
} else {
this.$apply(fn);
}
};
$scope.safeApply(function() {
alert('Now I'm wrapped for protection!');
});
I want to use $scope.$watch on my whole form inputs and detect changes and then show alert "Data has changed. Please save". The problem is that I want to pass oldValue only when the data is get from the server.
$http({
method: "post",
url: "url",
data: {
Pages: {
id: pageId
}
},
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function(data) {
$scope.data = data.editedPage.jkOutputContainer.editedPage.pagesObject;
$scope.$watch('data',function(newValue, oldValue) {
if(newValue != oldValue) {
$scope.dataHasChanged = true;
} else {
$scope.dataHasChanged = false;
}
}, true);
});
I could use ng-init and ng-change on every input in my form, but i would like to use the $scope.$watch on form.
EDIT: In short i want to hide alert when user back his changes to the state it was get from the server.
$scope.watch('[formname]', checkChanged, true)
function checkChanged(newVal) {
if (!angular.equals(newVal,$scope.data)) warnUser()
}
^This will watch every expression in the form and alert the user
To solve your problem, don't bind the server's response to a $scope variable, but just assign it to a variable that is referenced in the script. Here's an example.
$http({
method: "post",
url: "url",
data: {
Pages: {
id: pageId
}
},
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function(data) {
// To solve your problem, just store the server data in a variable.
var fromServer = data.editedPage.jkOutputContainer.editedPage.pagesObject;
$scope.data = fromServer; //<- Reference the var here.
$scope.$watch('data',function(newValue, oldValue) {
if(newValue != fromServer) { //<- Reference the var here.
$scope.dataHasChanged = true;
} else {
$scope.dataHasChanged = false;
}
}, true);
});
Hope that was helpful!