Removing Checkout Steps in Sylius - sylius

I'm working on removing both the shipping and the payment method steps from checkout in Sylius. There is a guide on how to remove the shipping step from checkout included in the Sylius docs here: http://docs.sylius.org/en/latest/cookbook/checkout.html
I've followed this guide and made additional changes to remove the payment method step as well (my shop will always use one payment method, no need for the user to select this). What's happening is that when I click next on the 'Address' step, I'm taken to the 'Complete' step, but then I'm immediately redirected back to the 'Address' step again, without error. My presumption is that I'll need to make the system aware of which shipping and which payment methods are to be used, but I don't see that code in the Sylius documentation anywhere.
Here are my changes:
app/Resources/SyliusCoreBundle/config/app/state_machine/sylius_order_checkout.yml:
states:
cart: ~
addressed: ~
completed: ~
transitions:
address:
from: [cart, addressed]
to: addressed
complete:
from: [payment_selected]
to: completed
I then ran this command, as suggested, to verify the state machine updates:
php bin/console debug:config winzou_state_machine
I can successfully see the two steps are removed in my sylius_order_config:
sylius_order_checkout:
class: Sylius\Component\Core\Model\Order
property_path: checkoutState
graph: sylius_order_checkout
state_machine_class: Sylius\Component\Resource\StateMachine\StateMachine
states:
cart: null
addressed: null
completed: null
transitions:
address:
from:
- cart
- addressed
to: addressed
complete:
from:
- payment_selected
to: completed
app/config/config.yml:
sylius_shop:
checkout_resolver:
route_map:
cart:
route: sylius_shop_checkout_address
addressed:
route: sylius_shop_checkout_complete
app/Resources/SyliusShopBundle/views/Checkout/_steps.html.twig:
{% if active is not defined or active == 'address' %}
{% set steps = {'address': 'active', 'complete': 'disabled'} %}
{% else %}
{% set steps = {'address': 'completed', 'complete': 'active'} %}
{% endif %}
<div class="ui four steps">
<a class="{{ steps['address'] }} step" href="{{ path('sylius_shop_checkout_address') }}">
<i class="map icon"></i>
<div class="content">
<div class="title">{{ 'sylius.ui.address'|trans }}</div>
<div class="description">{{ 'sylius.ui.fill_in_your_billing_and_shipping_addresses'|trans }}</div>
</div>
</a>
<div class="{{ steps['complete'] }} step" href="{{ path('sylius_shop_checkout_complete') }}">
<i class="checkered flag icon"></i>
<div class="content">
<div class="title">{{ 'sylius.ui.complete'|trans }}</div>
<div class="description">{{ 'sylius.ui.review_and_confirm_your_order'|trans }}</div>
</div>
</div>
</div>
app/Resources/SyliusShopBundle/config/routing/checkout.yml:
# This file is a part of the Sylius package.
# (c) Paweł Jędrzejewski
sylius_shop_checkout_start:
path: /
defaults:
_controller: FrameworkBundle:Redirect:redirect
route: sylius_shop_checkout_address
sylius_shop_checkout_address:
path: /address
methods: [GET, PUT]
defaults:
_controller: sylius.controller.order:updateAction
_sylius:
event: address
flash: false
template: SyliusShopBundle:Checkout:address.html.twig
form:
type: sylius_checkout_address
options:
customer: expr:service('sylius.context.customer').getCustomer()
repository:
method: find
arguments: [expr:service('sylius.context.cart').getCart()]
state_machine:
graph: sylius_order_checkout
transition: address
redirect:
route: sylius_shop_checkout_complete
parameters: []
#
#sylius_shop_checkout_select_shipping:
# path: /select-shipping
# methods: [GET, PUT]
# defaults:
# _controller: sylius.controller.order:updateAction
# _sylius:
# event: select_shipping
# flash: false
# template: SyliusShopBundle:Checkout:selectShipping.html.twig
# form: sylius_checkout_select_shipping
# repository:
# method: find
# arguments: [expr:service('sylius.context.cart').getCart()]
# state_machine:
# graph: sylius_order_checkout
# transition: select_shipping
# redirect:
# route: sylius_shop_checkout_select_payment
# parameters: []
#
#sylius_shop_checkout_select_payment:
# path: /select-payment
# methods: [GET, PUT]
# defaults:
# _controller: sylius.controller.order:updateAction
# _sylius:
# event: payment
# flash: false
# template: SyliusShopBundle:Checkout:selectPayment.html.twig
# form: sylius_checkout_select_payment
# repository:
# method: find
# arguments: [expr:service('sylius.context.cart').getCart()]
# state_machine:
# graph: sylius_order_checkout
# transition: select_payment
# redirect:
# route: sylius_shop_checkout_complete
# parameters: []
sylius_shop_checkout_complete:
path: /complete
methods: [GET, PUT]
defaults:
_controller: sylius.controller.order:updateAction
_sylius:
event: summary
flash: false
template: SyliusShopBundle:Checkout:complete.html.twig
repository:
method: find
arguments: [expr:service('sylius.context.cart').getCart()]
state_machine:
graph: sylius_order_checkout
transition: complete
redirect:
route: sylius_shop_order_pay
parameters:
paymentId: expr:service('sylius.context.cart').getCart().getLastNewPayment().getId()
form:
type: sylius_checkout_complete
options:
validation_groups: 'sylius_checkout_complete'
I cleared my cache, and the two additional steps are removed from checkout from what I can tell. Clicking next on the address step does send me to the final 'checkout' step, it just 302's me right back to the address step without an error.

I can spot one bug in your config file:
states:
cart: ~
addressed: ~
completed: ~
transitions:
address:
from: [cart, addressed]
to: addressed
complete:
from: [payment_selected] # <- here
to: completed
The complete transition should be done from addressed state instead of payment_selected (which does not exist in your configuration). It should resolve your problem.
You are also right, that default method resolvers are not documented yet. There are two classes responsible for assigning a default shipping and payment methods to order (DefaultPaymentMethodResolver and DefaultShippingMethodResolver). Both will assign the first available method. It should be an expected behaviour if you have only one method available. But feel free to override these classes to provide your custom logic :)

Related

Shopify Section load event in Liquid file (Shopify)

I am Shopify developer. I designed a slideshow using Flickity library in Shopify. My slider working fine on URL when load but it's not work on Shopify Theme Editor, till I am not saved the design. after save design is working fine.
I am using this script in section file it's not working but when I paste this code in theme.liquid file it's working fine on both sides.
I don't want like this image
<script>
{% if request.design_mode %}
console.log("123");
document.addEventListener("shopify:section:load", function() {
console.log("abc");
var elem = document.querySelector('.carousel');
var flkty = new Flickity( elem, {
autoPlay: "{{ section.settings.autoplay_slide }}",
pageDots: true,
contain: true,
wrapAround: false,
imagesLoaded: true,
accessibility: false
});
});
{% endif %}
</script>
I want, that when i select section from theme editor it's working smoothly.
I want like this image
Instead of using shopify:section:load which fires only inside the theme editor (that's why you can't get it working outside of theme editor), you should include this <script> tag in the end of your section's code and change it a bit:
<script>
{% if request.design_mode %}
console.log("123");
let flkty; // for later use
document.addEventListener("DOMContentLoaded", function() { // run this script after window is ready and scripts are loaded
console.log("abc");
var elem = document.querySelector('.carousel');
if (elem) { // check if element was found before using it
flkty = new Flickity( elem, {
autoPlay: "{{ section.settings.autoplay_slide }}",
pageDots: true,
contain: true,
wrapAround: false,
imagesLoaded: true,
accessibility: false
});
}
});
{% endif %}
</script>

Persisting id across components via params in Vue

I have a route path that looks like this /courses/:id/modules/:id, I am passing the :id of the course and modules via params like this
<router-link
:to="{
name: 'course-modules',
params: { id: item.id, onlineClassId: item.online_class_id }
}"
class="forum__link">
{{ item.title }}
</router-link>
I need to use the IDs to make a GET request.
But when I refresh the page, the component loses hold of onlineClassId which throws an error. Is there a way I persist that ID?
Thanks.
I figured the issue, in router.js I was using /courses/:id/modules/:id instead of courses/:onlineClassId/modules/:id

Dynamic routing in Vue.js, showing `this.$route.params.id` in html

I have a page that uses dynamic routing.
I have a "jobs" page that lists all jobs. One you click one job, it gives you the detail of that one job.
Jobs HTML page uses the following (snippets excludes ul/li tags):
<vue-panel v-for="job in jobs" v-if="filterJob(job)" v-bind:key="job.id">
Job: {{job.title}}<br>
Description: {{job.description}}<br>
Salary: ${{job.salary}}<br>
Date Posted: {{job.datePosted}}<br>
<router-link :to="`/job/${job.id}`">Learn More</router-link>
Clicking learn more leads to the correct job page. But how do I dynamically show just that specific job?
In the Job page, within the script I have:
created() {
console.log(this.$route.params.id); // prints value of :id
},
Via console log I see that it has access to the correct job page. But it is not dynamically showing that one job on the page. What needs to be in the HTML to access a specific job?
HTML of job page, as of now (excludes the ul/li tags):
<vue-panel v-bind:key="job.id">
Job: {{job.title}}<br>
Description: {{job.description}}<br>
Salary: ${{job.salary}}<br>
Date Posted: {{job.datePosted}}<br>
I built a similiar project and did the following.
router.js:
{
path: '/jobs/:id',
name: 'JobSingle',
component: JobSingle
}
jobs.vue
<router-link :to="{name:'JobSingle', params:{id:job._id}}">
{{ job.title }}
</router-link>
For more question you can have a look at my project here: github.com/markusdanek/t2w-vue
If you want to access by HTML you have to not bind key.
mounted(){
document.getElementById("H1").setAttribute("key", this.$route.params.id);
console.log('alex : ',document.getElementById("H1"));
}
When you use it by vue, you can't do by v-bind as type:
This works:
<div :type="$route.params.id">Verticals Statistics</div>
This don't work:
<div :key="$route.params.id">Verticals Statistics</div>
So you'll have to trick for passing a :key by vue, or as you did, with :
<div v-for='id in [$route.params.id]' :key="id">Verticals Statistics</div>
But it will not apear in HTML code.
You have to put an id on each and create the key attribute in the mounted part.

Change URI directly for a Vue app and caused error

In my Vue app, I can click a link generated by <router-link>...</router-link> and visit a page like: /site/books/00666.html.
The routing config for this is:
{
path: '/books/:id.html',
name: 'BookDetail',
component: BookDetail,
props: true,
}
So I changed the URI in the browser (Fx57) to: /site/books/00777.html to try to display the detail information of another book. It failed with this:
Cannot get /books/00777.html
and the debugger told me something like:
Content security policy is preventing from accessing a resource from 'self'`.
I searched on CSP but can't figure out how to make this working.
Update: To reproduce the issue, I use vue init webpack test and scafolded a blank Vue app with router support.
One new router is added:
{
path: '/book/:id.html',
name: 'BookDetail',
component: BookDetail,
props: true,
}
In the default HelloWorld.vue, just add a few lines with <router-link>:
<ul>
<li><router-link :to="{name: 'BookDetail', params: {id: 12345} }">Book 1</router-link></li>
<li><router-link :to="{name: 'BookDetail', params: {id: 23456} }">Book 2</router-link></li>
</ul>
In the HelloWorld page, clicking the link above will take you to "localhost:8080/book/12345.html". Good.
Change the URI to "localhost:8080/book/23456.html". The browser prompts the same error as before.
Update 2: per hint below, I modified the URI pattern to '/books/:id' and it is working.
Further question: What shall I do if I want to add the .html suffix?

v-link add linkActiveClass ,how to match routerName or (path and query)?

I have two v-link like this :
'/accountList?accountType=1': {
name: 'accountList1',
component: require('./../views/finance/accountList.vue')
},
'/accountList?accountType=2': {
name: 'accountList2',
component: require('./../views/finance/accountList.vue')
},
<li><a v-link=" { name: 'accountList1', exact: true } "><span>test1</span></a></li>
<li><a v-link=" { name: 'accountList2', exact: true } "><span>test2</span></a></li>
when i click one or them , both are added linkActiveClass .
Now,my problem is: how to controller the active status by routerName or path AND query?
Ps: exact: true, this is a wrong example,it is not fit here.
In this case I see two solutions
along with routerName you also need to compare query params which can be accessed by: this.$route.query. accountType
You can compare $route.fullPath which includes URL including query and hash.
But I am not sure why you have these two routes different: ideally these should be ideally same route with different query Param. Also have a look at this answer.
Per docs: https://router.vuejs.org/en/api/router-link.html
I would suggest to use:
<!-- with query, resulting in /register?plan=private -->
<router-link :to="{ path: 'accountType', query: { accountType: '1' }}"></router-link>
<router-link :to="{ path: 'accountType', query: { accountType: '2' }}"></router-link>