My API is getting called 2 times In Ionic - ionic-framework

I am working in my Ionic Project and my API is getting called 2 times. I am not able to get why my API is getting called 2 times.
This is my productdetails.html:
<ion-col *ngIf="hassizenot && product.out_of_stock == 0" style="padding: 0px;">
<button class="mybtn11" (click)="addtocartnew(product)" ion-button small>
Add to Cart
</button>
</ion-col>
This is my productdetails.ts:
addtocartnew(detailsp)
{
this.storage.get("ID").then((val) =>
{
if(val)
{
if(detailsp.SelectedSize)
{
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
size: detailsp.SelectedSize,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/'+detailsp.id+'/'+val+'/'+detailsp.SelectedSize).subscribe((data) => {
if (data) {
console.log("One");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else{
this.presentToasterror();
}
}
});
}
else
{
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/'+detailsp.id+'/'+val).subscribe((data) => {
if (data) {
console.log("Two");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else{
this.presentToasterror();
}
}
});
}
}
});
}
This is my Service:
usercartproducts(credentials, type) {
var headers = new HttpHeaders();
headers.append('Access-Control-Allow-Origin' , '*');
headers.append('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
headers.append('Accept','application/json');
headers.append('Content-Type','application/json');
headers.append('Access-Control-Allow-Credentials','true');
headers.append('Access-Control-Allow-Headers','Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
return this.http.post(apiUrl + type, credentials, {headers: headers});
}
In my ts file, I am running the API for adding the products to the cart and it is showing only one response in the console but it is calling 2 times because it is adding the 2 times the product and in the network in the chrome, it is calling 2 times.
Any help is much appreciated.

Just Try This In Your Service:
usercartproducts(credentials, type) {
var headers = new HttpHeaders();
headers.append('Access-Control-Allow-Origin' , '*');
headers.append('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT');
headers.append('Accept','application/json');
headers.append('Content-Type','application/x-www-form-urlencoded');
headers.append('Access-Control-Allow-Credentials','true');
headers.append('Access-Control-Allow-Headers','Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With');
let v = new FormData();
for(var k in credentials)v.append(k,credentials[k]);
return this.http.post(apiUrl + type, v, {headers: headers});
}
This solved my problem.

because you implement yout API twice and your If condition must be wrong
change your ts like this.
addtocartnew(detailsp) {
if (detailsp.SelectedSize) {
this.storage.get("ID").then((val) => {
if (val) {
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
size: detailsp.SelectedSize,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/' +
detailsp.id + '/' + val + '/' + detailsp.SelectedSize).subscribe((data) => {
console.log("One");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else {
this.presentToasterror();
}
}
});
}
})
}
else {
this.storage.get("ID").then((val) => {
if (val) {
let usercartnewdetails = {
user_id: val,
product_id: detailsp.id,
};
this.restProvider.usercartproducts(usercartnewdetails, 'user_cart/' +
detailsp.id + '/' + val).subscribe((data) => {
if (data) {
console.log("Two");
this.responseEdit = data;
console.log(this.responseEdit.msg);
if (this.responseEdit.status === 'success') {
this.presentToast(detailsp.product_name);
}
else {
this.presentToasterror();
}
}
});
}
})
}
}
change as per your condition and it will work.

Related

My dispatch method not working after dispatching in just iPhone Chrome (IOS 15.7.2)

I am working in Vue Js with Laravel. But specifically in iPhone Chrome my dispatch method is not working after dispatching. Please if anyone finds this type of issue in iPhone devices. Please provide any relevant solution.
Here the API Call code.
ProviderProfileService.addAddress(this.$apiUrl, this.address).then(
(response) => {
let result = response.data.createServiceLocation;
if (result.status == "success") {
let steps_status = JSON.parse(
result.service_location.user.providerProfileItems.profile_steps_status
);
if (steps_status.addrestime == true) {
alert(1);
this.$store
.dispatch("update_provider_profile_status", {
providerProfileStatus: steps_status,
})
.then((res) => {
alert(2);
this.$store.dispatch("update_progress_bar").then((res1) => {
if (response.data.createServiceLocation.status == "error") {
alert(0);
self.updateAddress();
} else {
this.$router.push(
"/provider-profile/language/" + this.userConfig.unique_identifier
);
alert(3);
// this.$router.push({
// name: "Language",
// params: { id: this.userConfig.unique_identifier },
// });
alert(4);
// window.location.href =
// "https://19b0-2404-3100-1c81-8081-e0bc-c658-121c-836b.ngrok.io/provider-profile/language/" +
// this.userConfig.unique_identifier;
this.scrollToTop();
alert(5);
}
});
});
}
}
},
(error) => {
self.content =
(error.response && error.response.data) || error.message || error.toString();
}
);
Here is the dispatch method code.
state.providerProfileStatus.basicinfo = (payload.basicinfo)?true:false;
state.providerProfileStatus.rates = (payload.rates)?true:false;
state.providerProfileStatus.services = (payload.services)?true:false;
state.providerProfileStatus.addrestime = (payload.addrestime)?true:false;
state.providerProfileStatus.availability = (payload.availability)?true:false;
state.providerProfileStatus.integrations = (payload.integrations)?true:false;
state.providerProfileStatus.certifications = (payload.certifications)?true:false;
state.providerProfileStatus.payment_settings = (payload.payment_settings)?true:false;
state.providerProfileStatus.documents_and_vaccination = (payload.documents_and_vaccination)?true:false;
state.providerProfileStatus.language_and_introduction = (payload.language_and_introduction)?true:false;

Ionic2 - http get is not working

I have written a authentication service to authenticate user name and password in a Login Page. The code below is the service.
public login(credentials) {
if (credentials.username === null || credentials.password === null) {
return Observable.throw("Please insert credentials");
} else {
let apiURL = 'http://localhost/timeclock/api/login?usercode=' + credentials.username +
'&password=' + credentials.password ;
return Observable.create(observer => {
this.http.get(apiURL).map(res => res.json()).subscribe(data => {
if (data.success === 'true')
{
this.currentUser.name = data.data.user_name;
this.currentUser.email = data.data.user_email;
observer.next(true);
observer.complete();
} else {
observer.next(false);
observer.complete();
}
});
});
}
}
When the user name and password is submitted, the URL is correctly called with the right parameters.
The http call takes very long time to complete. Also, no response is returned.
It takes only two or three seconds to get the response when I call the URL with the same parameters in the browser.
Any idea on how to fix this?
You don't need to create a new Observable you can refactor like this.
public login(credentials) : Observable<boolean> {
if (credentials.username === null || credentials.password === null) {
return Observable.throw("Please insert credentials");
} else {
let apiURL = 'http://localhost/timeclock/api/login?usercode=' + credentials.username +
'&password=' + credentials.password ;
return this.http.get(apiURL).map(res => res.json())
.map(data =>
{
if(data.success){
this.currentUser.name = data.data.user_name;
this.currentUser.email = data.data.user_email;
return true;
}else{
return false;
}
});
}
}

react-native-fbsdk - how to get user profile?

onLoginFinished's result just tells me the granted permissions. From the repo, not clear how to get the user profile. Seems like react-native-fbsdkcore should wrap FBSDKProfile.h but don't see where it does.
var FBSDKLogin = require('react-native-fbsdklogin');
var {
FBSDKLoginButton,
} = FBSDKLogin;
var Login = React.createClass({
render: function() {
return (
<View>
<FBSDKLoginButton
onLoginFinished={(error, result) => {
if (error) {
alert('Error logging in.');
} else {
if (result.isCanceled) {
alert('Login cancelled.');
} else {
alert('Logged in.');
}
}
}}
onLogoutFinished={() => alert('Logged out.')}
readPermissions={[]}
publishPermissions={['publish_actions']}/>
</View>
);
}
});
Found out you can get logged in user's profile with Graph API.
// Create a graph request asking for user's profile
var fetchProfileRequest = new FBSDKGraphRequest((error, result) => {
if (error) {
alert('Error making request.');
} else {
// Data from request is in result
}
}, '/me');
// Start the graph request.
fetchProfileRequest.start();
There is an easier way to do it. Rather than manually making the graph request yourself, 'react-native-fbsdkcore' package to get the data associated with the logged in user (if there is one)
var
FBSDKCore = require('react-native-fbsdkcore');
var {
FBSDKAccessToken,
} = FBSDKCore;
FBSDKAccessToken.getCurrentAccessToken((token) => {
// token will be null if no user is logged in,
// or will contain the data associated with the logged in user
});
cphackm address is that in this issue #2
Using #flow, here is a full example:
FbLogin.js
// #flow
import * as React from 'react';
import { View } from 'react-native';
import { LoginButton, AccessToken } from 'react-native-fbsdk';
import { FbService } from '#services';
import { toast } from '#libs/helpers';
type LoginResult = {
isCancelled: boolean,
grantedPermissions?: Array<string>,
declinedPermissions?: Array<string>
};
type Props = {
store: {
Account: Object
}
};
type State = {
token?: string
};
export default class Login extends React.Component<Props, State> {
componentDidMount() {
AccessToken.getCurrentAccessToken().then(tokenData => {
if (tokenData) {
console.log('[-- tokenData --]', tokenData);
const { accessToken, userID } = tokenData;
if (accessToken) {
console.log('[-- accessToken, userID --]', accessToken, userID);
this.setState({ token: accessToken });
// this._getUserInformation();
}
}
});
}
_getUserInformation = () => {
const { token } = this.state;
const { Account } = this.props.store;
if (token) {
FbService.getFbUserData(token, (error, result) => {
if (error) {
console.log('[-- error --]', error);
} else {
Account.provider = 'facebook';
Account.authorized = true;
Account.current = { password: '', token, ...result };
console.log('[-- responseFbUserData --]', result);
}
});
}
};
render() {
return (
<View>
<LoginButton
readPermissions={['public_profile']}
onLoginFinished={(error: Object, result: LoginResult) => {
if (error) {
alert('Login failed with error: ' + error.toString());
} else if (result.isCancelled) {
alert('Login was cancelled');
} else {
if (result) {
this._getUserInformation();
}
}
}}
onLogoutFinished={() => toast('User logged out', 'info')}
/>
</View>
);
}
}
/* AccessToken
accessToken: string,
applicationID: string,
userID: string,
permissions: Array<string>,
declinedPermissions: Array<string>,
accessTokenSource?: string,
expirationTime: number,
lastRefreshTime: number,
*/
FbService.js
// #flow
import * as React from 'react';
import { GraphRequestManager, GraphRequest, AccessToken } from 'react-native-fbsdk';
export function getFbUserData(token: string, callBack: Function) {
const profileRequestConfig = {
httpMethod: 'GET',
version: 'v2.12',
parameters: {
fields: {
string: 'id, name, email'
}
},
accessToken: token
};
const profileRequest = new GraphRequest('/me', profileRequestConfig, callBack);
new GraphRequestManager().addRequest(profileRequest).start();
}

How to reuse jquery-ui-autocomplete cached results when appending search term?

I have the following JS method to bind the jQuery UI autocomplete widget to a search text box. Everything works fine, including caching, except that I make unnecessary server calls when appending my search term because I don't reuse the just-retrieved results.
For example, searching for "ab" fetches some results from the server. Typing "c" after "ab" in the search box fetches "abc" results from the server, instead of reusing the cached "ab" results and omitting ones that don't match "abc".
I went down the path of manually looking up the "ab" search results, filtering them using a regex to select the "abc" subset, but this totally seems like I'm reinventing the wheel. What is the proper, canonical way to tell the widget to use the "ab" results, but filter them for the "abc" term and redisplay the shortened dropdown?
function bindSearchForm() {
"use strict";
var cache = new Object();
$('#search_text_field').autocomplete({
minLength: 2,
source: function (request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
$.ajax({type: 'POST',
dataType: 'json',
url: '/get_search_data',
data: {q: term},
success: function (data) {
cache[term] = data;
response(data);
}
});
});
}
Here's my "brute-force, reinventing the wheel" method, which is, for now, looking like the right solution.
function bindSearchForm() {
"use strict";
var cache = new Object();
var terms = new Array();
function cacheNewTerm(newTerm, results) {
// maintain a 10-term cache
if (terms.push(newTerm) > 10) {
delete cache[terms.shift()];
}
cache[newTerm] = results;
};
$('#search_text_field').autocomplete({
minLength: 2,
source: function (request, response) {
var term = request.term.toLowerCase();
if (term in cache) {
response(cache[term]);
return;
} else if (terms.length) {
var lastTerm = terms[terms.length - 1];
if (term.substring(0, lastTerm.length) === lastTerm) {
var results = new Array();
for (var i = 0; i < cache[lastTerm].length; i++) {
if (cache[lastTerm][i].label.toLowerCase().indexOf(term) !== -1) {
results.push(cache[lastTerm][i]);
}
}
response(results);
return;
}
}
$.ajax({type: 'POST',
dataType: 'json',
url: '/get_search_data',
data: {q: term},
success: function (data) {
cacheNewTerm(term, data);
response(data);
return;
}
});
});
}
If anyone wants a version that supports multiple entries in the text box then please see below:
$(function () {
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
var cache = new Object();
var terms = new Array();
function cacheNewTerm(newTerm, results) {
// keep cache of 10 terms
if (terms.push(newTerm) > 10) {
delete cache[terms.shift()];
}
cache[newTerm] = results;
}
$("#searchTextField")
.on("keydown",
function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).autocomplete("instance").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 2,
source: function (request, response) {
var term = extractLast(request.term.toLowerCase());
if (term in cache) {
response(cache[term]);
return;
} else if (terms.length) {
var lastTerm = terms[terms.length - 1];
console.log('LAst Term: ' + lastTerm);
if (term.substring(0, lastTerm.length) === lastTerm) {
var results = new Array();
for (var i = 0; i < cache[lastTerm].length; i++) {
console.log('Total cache[lastTerm[.length] = ' +
cache[lastTerm].length +
'....' +
i +
'-' +
lastTerm[i]);
console.log('Label-' + cache[lastTerm][i]);
var cachedItem = cache[lastTerm][i];
if (cachedItem != null) {
if (cachedItem.toLowerCase().indexOf(term) !== -1) {
results.push(cache[lastTerm][i]);
}
}
}
response(results);
return;
}
}
$.ajax({
url: '#Url.Action("GetSearchData", "Home")',
dataType: "json",
contentType: 'application/json, charset=utf-8',
data: {
term: extractLast(request.term)
},
success: function (data) {
cacheNewTerm(term, data);
response($.map(data,
function (item) {
return {
label: item
};
}));
},
error: function (xhr, status, error) {
alert(error);
}
});
},
search: function () {
var term = extractLast(this.value);
if (term.length < 2) {
return false;
}
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push("");
this.value = terms.join(", ");
return false;
}
});

alert() message isn't being called in my form

Firebug is giving me no error messages, but it's not working. The idea is regardless of whether the user picks an option from dropdown or if they type in something in search box, I want the alert() message defined below to alert what the value of the variable result is (e.g. {filter: Germany}). And it doesn't. I think the javascript breaks down right when a new Form instance is instantiated because I tried putting an alert in the Form variable and it was never triggered. Note that everything that pertains to this issue occurs when form.calculation() is called.
markup:
<fieldset>
<select name="filter" alter-data="dropFilter">
<option>Germany</option>
<option>Ukraine</option>
<option>Estonia</option>
</select>
<input type="text" alter-data="searchFilter" />
</fieldset>
javascript (below the body tag)
<script>
(function($){
var listview = $('#listview');
var lists = (function(){
var criteria = {
dropFilter: {
insert: function(value){
if(value)
return handleFilter("filter", value);
},
msg: "Filtering..."
},
searchFilter: {
insert: function(value){
if(value)
return handleFilter("search", value);
},
msg: "Searching..."
}
}
var handleFilter = function(key,value){
return {key: value};
}
return {
create: function(component){
var component = component.href.substring(component.href.lastIndexOf('#') + 1);
return component;
},
setDefaults: function(component){
var parameter = {};
switch(component){
case "sites":
parameter = {
'order': 'site_num',
'per_page': '20',
'url': 'sites'
}
}
return parameter;
},
getCriteria: function(criterion){
return criteria[criterion];
},
addCriteria: function(criterion, method){
criteria[criterion] = method;
}
}
})();
var Form = function(form){
var fields = [];
$(form[0].elements).each(function(){
var field = $(this);
if(typeof field.attr('alter-data') !== 'undefined') fields.push(new Field(field));
})
}
Form.prototype = {
initiate: function(){
for(field in this.fields){
this.fields[field].calculate();
}
},
isCalculable: function(){
for(field in this.fields){
if(!this.fields[field].alterData){
return false;
}
}
return true;
}
}
var Field = function(field){
this.field = field;
this.alterData = false;
this.attach("change");
this.attach("keyup");
}
Field.prototype = {
attach: function(event){
var obj = this;
if(event == "change"){
obj.field.bind("change", function(){
return obj.calculate();
})
}
if(event == "keyup"){
obj.field.bind("keyup", function(e){
return obj.calculate();
})
}
},
calculate: function(){
var obj = this,
field = obj.field,
msgClass = "msgClass",
msgList = $(document.createElement("ul")).addClass("msgClass"),
types = field.attr("alter-data").split(" "),
container = field.parent(),
messages = [];
field.next(".msgClass").remove();
for(var type in types){
var criterion = lists.getCriteria(types[type]);
if(field.val()){
var result = criterion.insert(field.val());
container.addClass("waitingMsg");
messages.push(criterion.msg);
obj.alterData = true;
alert(result);
initializeTable(result);
}
else {
return false;
obj.alterData = false;
}
}
if(messages.length){
for(msg in messages){
msgList.append("<li>" + messages[msg] + "</li");
}
}
else{
msgList.remove();
}
}
}
$('#dashboard a').click(function(){
var currentComponent = lists.create(this);
var custom = lists.setDefaults(currentComponent);
initializeTable(custom);
});
var initializeTable = function(custom){
var defaults = {};
var custom = custom || {};
var query_string = $.extend(defaults, custom);
var params = [];
$.each(query_string, function(key,value){
params += key + ': ' + value;
})
var url = custom['url'];
$.ajax({
type: 'GET',
url: '/' + url,
data: params,
dataType: 'html',
error: function(){},
beforeSend: function(){},
complete: function() {},
success: function(response) {
listview.html(response);
}
})
}
$.extend($.fn, {
calculation: function(){
var formReady = new Form($(this));
if(formReady.isCalculable) {
formReady.initiate();
}
}
})
var form = $('fieldset');
form.calculation();
})(jQuery)
Thank you for anyone who responds. I spent a lot of time trying to make this work.
The initial problem as to why the alert() was not being triggered when Form is instantiated is because, as you can see, the elements property belongs to the Form object, not fieldset object. And as you can see in the html, I place the fields as descendents of the fieldset object, not form.