Magento 2 checkout shipping rates collection - magento

I'm trying to trigger shipping rates recollection on checkout via 3d party JS code, not Knockout. What's the best way to trigger it?
Now I've replaced template onepage.phtml with custom one and trying this approach, but it doesn't work:
require([
'jquery',
'Magento_Checkout/js/model/quote'
], function($, quote) {
$('#target').on('click', function(e) {
console.log(quote.shippingAddress(quote.shippingAddress()));
});
});

ok, guys. Here is the solution:
require([
'jquery',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/shipping-service',
'Magento_Checkout/js/model/shipping-rate-registry',
'Magento_Checkout/js/model/shipping-rate-processor/customer-address',
'Magento_Checkout/js/model/shipping-rate-processor/new-address',
], function($, quote, shippingService, rateRegistry, customerAddressProcessor, newAddressProcessor) {
$('#target').on('click', function(e) {
var address = quote.shippingAddress();
// clearing cached rates to retrieve new ones
rateRegistry.set(address.getCacheKey(), null);
var type = quote.shippingAddress().getType();
if (type) {
customerAddressProcessor.getRates(address);
} else {
newAddressProcessor.getRates(address);
}
});
});

i already tried #c0rewell way
Company_Modulename/view/frontend/requirejs-config.js
var config = {
map: {
'*': {
company: 'Company_Modulename/js/myjs'
}
}
};
Company_Modulename/view/frontend/web/js/myjs.js
require([
'jquery',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/shipping-service',
'Magento_Checkout/js/model/shipping-rate-registry',
'Magento_Checkout/js/model/shipping-rate-processor/customer-address',
'Magento_Checkout/js/model/shipping-rate-processor/new-address',
], function($, quote, shippingService, rateRegistry, customerAddressProcessor, newAddressProcessor) {
$('div[name="shippingAddress.city"] select[name="city2"]').live('change', function(e) {
var address = quote.shippingAddress();
// clearing cached rates to retrieve new ones
rateRegistry.set(address.getCacheKey(), null);
var type = quote.shippingAddress().getType();
if (type) {
customerAddressProcessor.getRates(address);
} else {
newAddressProcessor.getRates(address);
}
});
});
above sciprt successfully force refresh the shipping cost, but the loading takeing forever
error from console
resource-url-manager.js:35 Uncaught TypeError: Cannot read property 'getQuoteId' of undefined
at Object.getUrlForEstimationShippingMethodsByAddressId (resource-url-manager.js:35)
at Object.getRates (customer-address.js:26)
at HTMLSelectElement.<anonymous> (xongkir.js:17)
at HTMLDocument.dispatch (jquery.js:4624)
at HTMLDocument.elemData.handle (jquery.js:4292)

#Ansyori
I have managed to run the estimat-shipping-methods by modifying code like below
require([
'jquery',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/shipping-service',
'Magento_Checkout/js/model/shipping-rate-registry',
'Magento_Checkout/js/model/shipping-rate-processor/customer-address',
'Magento_Checkout/js/model/shipping-rate-processor/new-address',
], function($, quote, shippingService, rateRegistry,
customerAddressProcessor, newAddressProcessor) {
$('div[name="shippingAddress.city"] select[name="city2"]').live('change', function(e) {
var address = quote.shippingAddress();
// clearing cached rates to retrieve new ones
rateRegistry.set(address.getCacheKey(), null);
var type = quote.shippingAddress().getType();
if (type == 'new-customer-address') {
newAddressProcessor.getRates(address);
}
});
});

Related

Watch Value In Vue.js 3, Equivalent In Pinia?

I have a checkbox list of domain tlds, such as com, net, io, etc. I also have a search text input, where I can drill down the list of 500 or so domains to a smaller amount. For example, if I start to type co in to my search text input, I will get back results that match co, such as co, com, com.au, etc. I am using Laravel and Vue,js 3 to achieve this with a watcher. It works beautifully. How can an achieve the same within a Pinia store?
Here is my code currently:
watch: {
'filters.searchedTlds': function(after, before) {
this.fetchsearchedTlds();
}
},
This is inside my vue component.
Next is the code to fetch searched tlds:
fetchsearchedTlds() {
self = this;
axios.get('/fetch-checked-tlds', { params: { searchedTlds: self.filters.searchedTlds } })
.then(function (response) {
self.filters.tlds = response.data.tlds;
console.log(response.data.tlds);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
},
And finally, the code inside my Laravel controller:
public function fetchCheckedTlds(Request $request)
{
$data['tlds'] = Tld::where('tld', 'LIKE','%'.$request->input('searchedTlds').'%')->pluck('tld');
return response()->json($data);
}
I am converting my code to use a Pinia store and I am stuck on how to convert my vue component watcher to Pinia?
Many thanks in advance.
To watch a pinia status, you may watch a computed attribute based on pinia or use watch getter
Your pinia may look like the one below.
~/store/filters.js
export const useFilters = defineStore('filters', {
state: () => {
return {
_filters: {},
};
},
getters: {
filters: state => state._filters,
},
...
}
In where you want to watch
<script setup>
import { computed, watch } from 'vue';
import { useFilters } from '~/store/filters.js';
const filters = useFilters();
// watch a computed attributes instead
const searchedTlds = computed(() => {
return filters.filters?.searchedTlds || '';
});
watch(
searchedTlds,
(newValue, oldValue) {
fetchsearchedTlds();
}
);
// or use watch getter
watch(
() => {
return filters.filters?.searchedTlds || '';
},
(newValue, oldValue) {
fetchsearchedTlds();
}
);
</script>
The first parameter of watch() can be a single ref or a getter function, or an array of getter functions, for more details, please view the Watch Source Types.

How to load AJAX in react

Im trying to get my json result into my react code
The code looks like the following
_getComments() {
const commentList = "AJAX JSON GOES HERE"
return commentList.map((comment) => {
return (
<Comment
author={comment.author}
body={comment.body}
avatarUrl={comment.avatarUrl}
key={comment.id} />);
});
}
How do i fetch AJAX into this?
First, to fetch the data using AJAX, you have a few options:
The Fetch API, which will work out of the box in some browsers (you can use a polyfill to get it working in other browsers as well). See this answer for an example implementation.
A library for data fetching (which generally work in all modern browsers). Facebook recommends the following:
superagent
reqwest
react-ajax
axios
request
Next, you need to use it somewhere in your React component. Where and how you do this will depend on your specific application and component, but generally I think there's two scenarios to consider:
Fetching initial data (e.g. a list of users).
Fetching data in response to some user interaction (e.g. clicking a
button to add more users).
Fetching initial data should be done in the life-cycle method componentDidMount(). From the React Docs:
var UserGist = React.createClass({
getInitialState: function() {
return {
username: '',
lastGistUrl: ''
};
},
componentDidMount: function() {
this.serverRequest = $.get(this.props.source, function (result) {
var lastGist = result[0];
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
}.bind(this));
},
componentWillUnmount: function() {
this.serverRequest.abort();
},
render: function() {
return (
<div>
{this.state.username}'s last gist is
<a href={this.state.lastGistUrl}>here</a>.
</div>
);
}
});
ReactDOM.render(
<UserGist source="https://api.github.com/users/octocat/gists" />,
mountNode
);
Here they use jQuery to fetch the data. While that works just fine, it's probably not a good idea to use such a big library (in terms of size) to perform such a small task.
Fetching data in response to e.g. an action can be done like this:
var UserGist = React.createClass({
getInitialState: function() {
return {
users: []
};
},
componentWillUnmount: function() {
this.serverRequest && this.serverRequest.abort();
},
fetchNewUser: function () {
this.serverRequest = $.get(this.props.source, function (result) {
var lastGist = result[0];
var users = this.state.users
users.push(lastGist.owner.login)
this.setState({ users });
}.bind(this));
},
render: function() {
return (
<div>
{this.state.users.map(user => <div>{user}</div>)}
<button onClick={this.fetchNewUser}>Get new user</button>
</div>
);
}
});
ReactDOM.render(
<UserGist source="https://api.github.com/users/octocat/gists" />,
mountNode
);
Lets take a look on the fetch API : https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
Lets say we want to fetch a simple list into our component.
export default MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
lst: []
};
this.fetchData = this.fetchData.bind(this);
}
fetchData() {
fetch('url')
.then((res) => {
return res.json();
})
.then((res) => {
this.setState({ lst: res });
});
}
}
We are fetching the data from the server, and we get the result from the service, we convert is to json, and then we set the result which will be the array in the state.
You can use jQuery.get or jQuery.ajax in componentDidMount:
import React from 'react';
export default React.createClass({
...
componentDidMount() {
$.get('your/url/here').done((loadedData) => {
this.setState({data: loadedData});
});
...
}
First I'd like to use fetchAPI now install of ajax like zepto's ajax,the render of reactjs is asyn,you can init a state in the constructor,then change the state by the data from the result of fetch.

How to refresh content when using CrossroadJS and HasherJS with KnockoutJS

I was following Lazy Blogger for getting started with routing in knockoutJS using crossroads and hasher and it worked correctly.
Now I needed to refresh the content using ajax for Home and Settings page every time they are clicked. So I googled but could not find some useful resources. Only these two links
Stack Overflow Here I could not understand where to place the ignoreState property and tried these. But could not make it work.
define(["jquery", "knockout", "crossroads", "hasher"], function ($, ko, crossroads, hasher) {
return new Router({
routes:
[
{ url: '', params: { page: 'product' } },
{ url: 'log', params: { page: 'log' } }
]
});
function Router(config) {
var currentRoute = this.currentRoute = ko.observable({});
ko.utils.arrayForEach(config.routes, function (route) {
crossroads.addRoute(route.url, function (requestParams) {
currentRoute(ko.utils.extend(requestParams, route.params));
});
});
activateCrossroads();
}
function activateCrossroads() {
function parseHash(newHash, oldHash) {
//crossroads.ignoreState = true; First try
crossroads.parse(newHash);
}
crossroads.normalizeFn = crossroads.NORM_AS_OBJECT;
hasher.initialized.add(parseHash);
hasher.changed.add(parseHash);
hasher.init();
$('a').on('click', function (e) {
crossroads.ignoreState = true; //Second try
});
}
});
Crossroads Official Page Here too I could not find where this property need to be set.
If you know then please point me to some url where I can get more details about this.

error is not a constructor

I am new to backbone and requirejs...
I am working on a small gallery app where i came across this error in firefox firebug and in chrome it doesn't show any error chrome dev tool... please help me in this
here is my code
PhotosCollectionjs
define([
'jquery',
'underscore',
'backbone',
'models/thumb/PhotoModel'
], function ($, _, Backbone, PhotoModel) {
var PhotosCollection = Backbone.Collection.extend({
model: PhotoModel,
url: '/photos?query=xxx',
fetch: function (options) {
options = options || {};
.......
Backbone.Collection.prototype.fetch.call(this, options);
},
parse: function (response) {
......
return response.photos;
}
});
return PhotosCollection;
});
loadphotos js
define([
'jquery',
'underscore',
'backbone',
'collections/thumb/PhotosCollection'
], function ($, _, Backbone, PhotosCollection) {
console.log(PhotosCollection); .... undefined(firebug) ... function (){return r.apply(this,arguments)} (chrome dev tool)
var loadPhotos = function (container, options) {
var photos;
photos = void 0;
if (options) {
photos = new PhotosCollection();
options.collection = photos;
}
.....................
................
};
return loadPhotos;
});
in firebug it is giving error
TypeError: PhotosCollection is not a constructor
photos = new PhotosCollection();
EDIT
its temporarily solved .... but now again after few refreshes i receive same error in firebug but no error in chrome... Please someone help me
Edit 2
Trial and error i found that it occurs only while debugging with breakpoints.... if i remove all breakpoints its giving no error... is it related to async loading of scripts or something else???
i just included initialize in PhotosCollection js and now its giving no error... i dont know what exactly the problem but it got solved.....
But i am interested in knowing the cause for it... as only firebug thrown error and chrome doesn't... Please give me some insight
here is my new photosCollection js with blank intialize....
define([
'jquery',
'underscore',
'backbone',
'models/thumb/PhotoModel'
], function ($, _, Backbone, PhotoModel) {
var PhotosCollection = Backbone.Collection.extend({
model: PhotoModel,
url: '/photos?query=xxx',
initialize:function(options){},
fetch: function (options) {
options = options || {};
.......
Backbone.Collection.prototype.fetch.call(this, options);
},
parse: function (response) {
......
return response.photos;
}
});
return PhotosCollection;
});

jQuery Mobile iScrollView error

I am using jQuery Mobile and iScrollview together,
I used iscrollView
The scrolling work fine.
Problem 1:
when I click on a input text/password field, I get an extra box overlapping the whole elements, which has the same content as the input.
same problem found in
here no solution
Problem 2:
when navigating to next page, the previous page remains behind new page and when tap the mobile screen the previous page goes off from the device. this is not happening in the webbrowsers.
Any suggestions,
code for main.js
require.config({
paths: {
jquery: '../lib/jquery',
'jquery.mobile-config': 'helper/jqm-config',
'jquery.mobile': '../lib/jquery.mobile-1.2.1.min',
underscore: '../lib/underscore-min',
backbone: '../lib/backbone-min',
templates: '../templates',
text: 'helper/text',
config: 'helper/config',
'backbone.subroute': '../lib/backbone.subroute',
'cookie': '../lib/jquery.cookie',
'maskInput': '../lib/Jquerymaskinput',
'iscroll': '../lib/iscroll',
'iscrollview': '../lib/jquery.mobile.iscrollview',
}
,
shim: {
'underscore': {
exports: "_"
},
'backbone': {
//These script dependencies should be loaded before loading
//backbone.js
deps: ['jquery', 'underscore'],
//Once loaded, use the global 'Backbone' as the
//module value.
exports: 'Backbone'
},
'jquery.mobile-config': ['jquery'],
'jquery.mobile': ['jquery', 'jquery.mobile-config'],
'backbone.subroute': ['jquery', 'underscore', 'backbone'],
//'backbone.oauth':['jquery','underscore','backbone'],
'iscroll': {
deps: ['jquery.mobile']
},
'iscrollview': {
deps: ['iscroll']
},
'config': {
exports: 'Config'
}
}
});
requirejs(['jquery', 'iscroll', 'jquery.mobile', 'iscrollview'], function($, iScroll) {
var elements = jQuery(document).find(":jqmData(iscroll)");
elements.iscrollview();
});
require([
'app'
], function(App) {
App.initialize();
});
for router
define([
'jquery',
'underscore',
'backbone',
'backbone.subroute'
], function($, _, Backbone) {
var AppRouter = Backbone.Router.extend({
routes: {
// general routes
'': 'defaultAction',
'login':'login',
'menu': 'mainMenu',
// Default
'*actions': 'defaultAction'
}
});
var initialize = function() {
$('.back').live('click', function(event) {
event.preventDefault();
window.history.back();
return false;
});
var app_router = new AppRouter;
app_router.on('route:defaultAction', function(actions) {
require(['views/home/register'], function(RegisterView) {
// We have no matching route, lets display the home page
console.log('At defaultAction');
var registerView = new RegisterView();
registerView.render();
/// this.changePage(loginView, 'slide');
});
});
app_router.on('route:login', function(actions) {
require(['views/home/login'], function(LoginView) {
// We have no matching route, lets display the home page
console.log('At defaultAction');
var loginView = new LoginView();
loginView.render();
/// this.changePage(loginView, 'slide');
});
});
app_router.on('route:mainMenu', function(actions) {
require(['views/home/menu'], function(MainMenuView) {
console.log('At mainMenu::router');
var mainMenuView = new MainMenuView();
mainMenuView.render();
// this.changePage(mainMenuView, 'slide');
});
});
Backbone.history.start();
};
return {
initialize: initialize
};
});
I rewrite the codes but, its more or less solved my problem updated the jqm to 1.3 and jquery to 1.9.
rewrite all css files.
Navigation to next page is fine
and at least its working now.
Thanks to Omar who helped me.
gracias mi amigo

Resources