I am trying to add my new shipping method with a map (INPOST) but I have a problem. My map won't load. Then I try to use a case with no map, with points but still not working in the checkout. I tried to do this on the product page and it worked.
My custom shipping method working good, only problem with that map
Documentation: https://docs.inpost24.com/pages/viewpage.action?pageId=7798862
Magento version: 2.3
Bellow my codes:
app/code/Kitsune/Inpost/view/frontend/layout/checkout_index_index.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<script src="https://geowidget.easypack24.net/js/sdk-for-javascript.js" src_type="url" async="async"/>
<css src="https://geowidget.easypack24.net/css/easypack.css" src_type="url"/>
</head>
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shipping-step" xsi:type="array">
<item name="children" xsi:type="array">
<item name="shippingAddress" xsi:type="array">
<item name="config" xsi:type="array">
<item name="shippingMethodItemTemplate" xsi:type="string">Kitsune_Inpost/custom-method-item-template</item>
<item name="shippingMethodListTemplate" xsi:type="string">Kitsune_Inpost/custom-method-list-template</item> </item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
app/code/Kitsune/Inpost/view/frontend/web/js/inpost.js
jQuery( document ).ready(function() {
easyPack.init({
instance: 'pl',
mapType: 'osm',
searchType: 'osm',
points: {
types: ['parcel_locker'],
},
map: {
useGeolocation: true,
initialTypes: ['parcel_locker']
}
})
window.onload = function() {
easyPack.dropdownWidget('easypack-widget', function(point) {
console.log(point)
});
}
});
app/code/Kitsune/Inpost/view/frontend/web/template/custom-method-item-template.html
<!-- Initialize collapsible binding -->
<tbody collapsible="as: '$collapsible_' + method.method_code">
<tr class="row">
<td class="col col-method">
<input type="radio"
class="radio"
click="element.selectShippingMethod"
ifnot="method.error_message"
ko-checked="element.isSelected"
ko-value="method.carrier_code + '_' + method.method_code"
attr="'aria-labelledby': 'label_method_' + method.method_code + '_' + method.carrier_code + ' ' + 'label_carrier_' + method.method_code + '_' + method.carrier_code,
'checked': element.rates().length == 1 || element.isSelected" />
</td>
<td class="col col-price">
<each args="element.getRegion('price')" render="" />
</td>
<td class="col col-method"
attr="'id': 'label_method_' + method.method_code + '_' + method.carrier_code"
text="method.method_title" />
<td class="col col-carrier"
attr="'id': 'label_carrier_' + method.method_code + '_' + method.carrier_code"
text="method.carrier_title" />
<!-- Column with collapsible trigger -->
<td class="col">
<!-- ko if: method.carrier_code == 'kitsune_inpost' -->
<div data-bind="mageInit: {'inpost': {}}" id="easypack-widget"></div>
<h1>eloo</h1>
<!-- /ko -->
</td>
</tr>
<!-- Row for shipping method description -->
<tr class="row" visible="$context['$collapsible_' + method.method_code].opened">
<td class="col" colspan="5" i18n="'Some description.'"/>
</tr>
<tr class="row row-error"
if="method.error_message">
<td class="col col-error" colspan="5">
<div role="alert" class="message error">
<div text="method.error_message"></div>
</div>
<span class="no-display">
<input type="radio"
attr="'value' : method.method_code, 'id': 's_method_' + method.method_code" />
</span>
</td>
</tr>
</tbody>
app/code/Kitsune/Inpost/view/frontend/web/template/custom-method-list-template.html
<div id="checkout-shipping-method-load">
<table class="table-checkout-shipping-method" markdown="1"> <thead>
<tr class="row" markdown="1">
<th class="col col-method" translate="'Select Method'" />
<th class="col col-price" translate="'Price'" />
<th class="col col-method" translate="'Method Title'" />
<th class="col col-carrier" translate="'Carrier Title'" />
<!-- Column for triggers -->
<th class="col" />
</tr>
</thead> <!-- tbody was moved inside item template --> <!-- ko foreach: { data: rates(), as: 'method'} --> <!--ko template: { name: element.shippingMethodItemTemplate} --><!-- /ko --> <!-- /ko --> </table>
</div>
app/code/Kitsune/Inpost/view/frontend/requirejs-config.js
var config = {
map: {
'*': {
inpost: 'Kitsune_Inpost/js/inpost'
}
}
}
I wanted to add just comment instead of posting an answer (but I can't comment).
Wrap your js in define and check comments I added here:
define(['domReady!'], function() {
// check here via debugger if code is executed
// then you can investigate why rest isn't working
window.easyPack.init({
instance: 'pl',
mapType: 'osm',
searchType: 'osm',
points: {
types: ['parcel_locker'],
},
map: {
useGeolocation: true,
initialTypes: ['parcel_locker']
}
});
// this also won't work as you can miss onload event
window.onload = function() {
easyPack.dropdownWidget('easypack-widget', function(point)
{
console.log(point)
});
};
});
you need be sure that easyPack will be available. Do you load it synchronously? I see some async version in documentation so you need to think about that and implement it properly.
Related
I am trying to figure out what I've missed during my coding on my project. My problem is my datatable format/style is not what it seems to look like from standard format. I'm using ASP.net MVC.
This is the output: Page numbers, search box is not in style
Page numbers, search box is not in style
Here is my code:
<div class="row">
<div class="col-sm-20c">
<div class="panel-body">
<table id="tbl-transaction" class="table table-bordered" cellspacing="0" width="100%" align="center">
<thead>
<tr>
<th>Transaction No</th>
<th>Purpose of Visit</th>
<th>Name of Host</th>
<th>Transacted By</th>
<th>Details</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
#section Scripts
{
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.dataTables.min.js"></script>
<script>
getall();
function getall()
{
$('#tbl-transaction').dataTable().fnDestroy();
$('#tbl-transaction').DataTable({
"ajax": {
"url": '/FSEWeb/Admin/GetAllTransactions',
"type": "get",
"datatype" : "JSON"
},
"columns" :
[
{ data :"TransactionNumber"},
{ data: "PurposeOfVisit" },
{ data: "NameOfHostFromST" },
{ data: "TransactedBy" },
{
data: null, "render" : function(data,type,row)
{
return '<button class= "btn btn-success" onclick = "get_details(' + data.id + ',' + data.TransactionNumber + ')"> Details </button>';
}
}
]
})
}
This table format is what I want to look like.
Desired output with styles
You have not incorporated JQuery Datatbles style sheet i.e.
<!-- Data table -->
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.10/css/dataTables.bootstrap.min.css " />
Incorporate it at layout level or page level.
I have create custom checkout Step between shipping and payment step . Now i want to show all the order details and customer fillup details.
Below is the files that i have created for the Custom checkout step
Below is the file (checkout_index_index.xml) i have created for new step in the checkout :
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<!-- The new step you add -->
<item name="my-new-step" xsi:type="array">
<item name="component" xsi:type="string">Mycustom_Checkoutnew/js/view/my-step-view</item>
<!--To display step content before shipping step "sortOrder" value should be < 1-->
<!--To display step content between shipping step and payment step 1 < "sortOrder" < 2 -->
<!--To display step content after payment step "sortOrder" > 2 -->
<item name="sortOrder" xsi:type="string">1</item>
<item name="children" xsi:type="array">
<!--add here child component declaration for your step-->
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
In the second file (my-step-view.js) there will be js code as follow :
define([
'ko',
'uiComponent',
'underscore',
'Magento_Checkout/js/model/step-navigator'
], function (ko, Component, _, stepNavigator) {
'use strict';
/**
* mystep - is the name of the component's .html template,
* <Vendor>_<Module> - is the name of your module directory.
*/
return Component.extend({
defaults: {
template: 'Mycustom_Checkoutnew/mystep'
},
// add here your logic to display step,
isVisible: ko.observable(true),
/**
* #returns {*}
*/
initialize: function () {
this._super();
// register your step
stepNavigator.registerStep(
// step code will be used as step content id in the component template
'shippingaddress',
// step alias
null,
// step title value
'Shipping',
// observable property with logic when display step or hide step
this.isVisible,
_.bind(this.navigate, this),
/**
* sort order value
* 'sort order value' < 10: step displays before shipping step;
* 10 < 'sort order value' < 20 : step displays between shipping and payment step
* 'sort order value' > 20 : step displays after payment step
*/
15
);
return this;
},
/**
* The navigate() method is responsible for navigation between checkout steps
* during checkout. You can add custom logic, for example some conditions
* for switching to your custom step
* When the user navigates to the custom step via url anchor or back button we_must show step manually here
*/
navigate: function () {
this.isVisible(true);
},
/**
* #returns void
*/
navigateToNextStep: function () {
stepNavigator.next();
}
});
});
Below is the html file (mystep.html) where i want to display all the data of orders and the customer
<li id="shippingaddress" data-bind="fadeVisible: isVisible">
<div class="step-title" data-bind="i18n: 'Shipping'" data-role="title"></div>
<div id="checkout-step-title"
class="step-content"
data-role="content">
<form data-bind="submit: navigateToNextStep" novalidate="novalidate">
<div class="actions-toolbar">
<div class="primary">
<button data-role="opc-continue" type="submit" class="button action continue primary">
<span><!-- ko i18n: 'Next'--><!-- /ko --></span>
</button>
</div>
</div>
</form>
</div>
</li>
In the new custom page i want show following things
1)Email 2)Contact 3 ) Address that sellected in previous step
4)Shipping method
If anyone can help me in this then please let me know
In frontend i want to show data as per image attached. go through that image
I'm using VUE 2.5.1 & iView 4.0.0. There are 2 forms in a page of my project, and I use v-if property to switch them. The problem is after I re-assign the value of form_data (the new one does not have property 'usage') and set this.met_type to 3, the 'Item' input showes, but a line of red text 'usage is required' also showes under it. The 'Usage' input is already hidden, why does its validation tips still show? Is there a way to avoid this wrong message?
<template>
<div v-if="met_type==2">
<Form :rules="ruleCustom" :model="form_data">
<Row>
<Col span="12">
<FormItem label="Usage" prop="usage" required>
<Input :value="form_data.usage" readonly />
</FormItem>
</Col>
</Row>
<!-- other code omitted -->
</Form>
</div>
<div v-if="met_type==3">
<Form :rules="ruleCustom" :model="form_data">
<Row>
<Col span="12">
<FormItem label="Item" prop="item" required>
<Input :value="form_data.item" readonly />
</FormItem>
</Col>
</Row>
<!-- other code omitted -->
</Form>
</div>
<!-- other code omitted -->
</template>
<script>
export default {
methods: {
loadData: function(met_type) {
dataUtils.fetch(this.met_id, met_type, (retVal) => {
// Fetch data
// whe met_type == 3, form_data does not have property 'usage'
this.form_data = retVal.data;
this.met_type = met_type;
});
}
}
}
</script>
After I put these two forms into seperate template files, the problem is solved. But I still don't understand why this takes effective.
// ComponentA.vue
<template>
<Form :rules="ruleCustom" :model="form_data">
<Row>
<Col span="12">
<FormItem label="Usage" prop="usage" required>
<Input :value="form_data.usage" readonly />
</FormItem>
</Col>
</Row>
<!-- other code omitted -->
</Form>
</template>
// ComponentB.vue
<template>
<Form :rules="ruleCustom" :model="form_data">
<Row>
<Col span="12">
<FormItem label="Item" prop="item" required>
<Input :value="form_data.item" readonly />
</FormItem>
</Col>
</Row>
<!-- other code omitted -->
</Form>
</template>
// The main component file
<template>
<div v-if="met_type==2">
<ComponentA>
</ComponentA>
</div>
<div v-if="met_type==3">
<ComponentB>
</ComponentB>
</div>
<!-- other code omitted -->
</template>
<script>
export default {
methods: {
loadData: function(met_type) {
dataUtils.fetch(this.met_id, met_type, (retVal) => {
// Fetch data
// whe met_type == 3, form_data does not have property 'usage'
this.form_data = retVal.data;
this.met_type = met_type;
});
}
}
}
</script>
1,
2,
Question:When do we change images dynamically ?
Answer: When user asynchronously upload images, such as using ajaxfileupload.js.
when a user upload one image, and want to upload another one.
If he uses Jcrop, the later images are all shown in size of the first image.
even though he uses following jQuery code to change the size of the new image, it`s still in wrong size.
$("#target").attr("width","400");
$("#target").attr("height","250");
Does anyone know how to use Jcrop and show each images in its real size? I mean when the images is dynamically changed.
Thanks a lot!
The souce code is compressed into a zip file, they are all font-end code, so you may open it once it`s unzipped, please open "crop.html"
you may download the zip file (214KB) here:
download
the content of "crop.html" is:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="js/jquery.min.js"></script>
<script src="js/jquery.Jcrop.js"></script>
<script type="text/javascript">
jQuery(function($) {
var jcrop_api;
initJcrop();
$('#coords').on('change', 'input', function(e) {
var x1 = $('#x1').val(),
x2 = $('#x2').val(),
y1 = $('#y1').val(),
y2 = $('#y2').val();
jcrop_api.setSelect([x1, y1, x2, y2]);
});
function initJcrop() {
$('#target').Jcrop({
onChange: showCoords,
onSelect: showCoords,
onRelease: clearCoords
}, function() {
jcrop_api = this;
});
};
$('#changeToWiderPicture').click(function(e) {
jcrop_api.destroy();
$("#target").attr("src", "img/2.jpg");
$("#target").attr("width", "400");
$("#target").attr("height", "250");
$("#normalPicture").attr("src", "img/2.jpg");
$("#normanPicureIntroduction").html("Original picure:400X250");
$('#changeToWiderPicture').hide();
$('#changeBack').show();
initJcrop();
return false;
});
$('#changeBack').click(function(e) {
jcrop_api.destroy();
$("#target").attr("src", "img/1.jpg");
$("#normalPicture").attr("src", "img/1.jpg");
$("#normanPicureIntroduction").html("Original picure:250X400");
$('#changeBack').hide();
$('#changeToWiderPicture').show();
initJcrop();
return false;
});
});
function showCoords(c) {
$('#x1').val(c.x);
$('#y1').val(c.y);
$('#x2').val(c.x2);
$('#y2').val(c.y2);
$('#w').val(c.w);
$('#h').val(c.h);
};
function clearCoords() {
$('#coords input').val('');
};
</script>
<link rel="stylesheet" href="css/main.css" type="text/css" />
<link rel="stylesheet" href="css/demos.css" type="text/css" />
<link rel="stylesheet" href="css/jquery.Jcrop.css" type="text/css" />
</head>
<body>
<table>
<tr>
<td>
<img src="img/1.jpg" id="target" />
<br>Picture with Jcrop attached
</td>
<td width=40%></td>
<td>
<img src="img/1.jpg" id="normalPicture" />
<br>
<span id='normanPicureIntroduction'>Original picure:250X400</span>
</td>
</tr>
</table>
<form id="coords" class="coords">
<div class="inline-labels">
<label>X1
<input type="text" size="4" id="x1" name="x1" />
</label>
<label>Y1
<input type="text" size="4" id="y1" name="y1" />
</label>
<label>X2
<input type="text" size="4" id="x2" name="x2" />
</label>
<label>Y2
<input type="text" size="4" id="y2" name="y2" />
</label>
<label>W
<input type="text" size="4" id="w" name="w" />
</label>
<label>H
<input type="text" size="4" id="h" name="h" />
</label>
</div>
</form>
<div style="padding-top:20px;">
<button id="changeToWiderPicture" class="btn btn-mini">changeToWiderPicture</button>
<button id="changeBack" class="btn btn-mini" style="display:none;">changeBack</button>
</div>
</body>
</html>
I find a solution from another answer on another question:
use -
$('#image').removeAttr('style');
Or simply overwrite the corresponding CSS style, for example -
$("#target").css({"width":"400px" ,"height":"250px"});
please be aware:
CSS style has a higher priority than the attribute, so sometimes, you find your change does not apply, for example -
$("#target").attr("width","400");
$("#target").attr("height","250");
So, for safer, user CSS style instead of an attribute.
I used ajax validation to validate the following
<tr>
<td width="20" style='color: red'>
<img src="images/icon-star.png" width="16" height="16" />
</td>
<td id="lblCustomBillNo" style="width: 15%" class="searchCriteriaCellLbl">
The custom Bill Number
</td>
<td width="5" class="searchCriteriaCellLbl">:</td>
<td class="searchCriteriaCellVal">
<s:textfield id="customBillNo" name="customBillNo" size="20" maxlength="24" style="width: 200px" />
</td>
<td class="errorFlag" style="color: red" valign="middle">
<s:fielderror fieldName="customBillNo" />
</td>
</tr>
<tr>
<td width="20" style='color: red'>
<img src="images/icon-star.png" width="16" height="16" />
</td>
<td id="lblBillNo" style="width: 15%" class="searchCriteriaCellLbl">
<s:property value="%{getText('billNo')}" />
</td>
<td width="5" class="searchCriteriaCellLbl">:
</td>
<td class="searchCriteriaCellVal">
<s:textfield label="billNo" id="billNo" name="billNo" size="20" maxlength="24" style="width: 200px" />
</td>
<td class="errorFlag" style="color: red" valign="middle">
<s:fielderror fieldName="billNo" />
</td>
</tr>
<tr>
<td width="20" style='color: red'>
<img src="images/icon-star.png" width="16" height="16" />
</td>
<td id="lblCarrierNo" style="width: 15%" class="searchCriteriaCellLbl">
The carrier Number
</td>
<td width="5" class="searchCriteriaCellLbl">:
</td>
<td class="searchCriteriaCellVal">
<s:textfield label="carrierNo" id="carrierNo" name="carrierNo" size="20" maxlength="24" style="width: 200px" />
</td>
<td class="errorFlag" style="color: red" valign="middle">
<s:fielderror fieldName="carrierNo" />
</td>
</tr>
I use the following internationalization for errors in golbal i18n file
errors.required=${getText(fieldName)} requireddd
and this validation file
<validators>
<field name="customBillNo">
<field-validator type="requiredstring" short-circuit="true">
<param name="trim">true</param>
<message key="errors.required" />
</field-validator>
</field>
<field name="billNo">
<field-validator type="required" short-circuit="true">
<message key="errors.required" />
</field-validator>
</field>
<field name="carrierNo">
<field-validator type="required" short-circuit="true">
<message key="errors.required" />
</field-validator>
</field>
</validators>
and i put this javascript to use ajax validation
function validate(){
//document.all.loading.style.display = 'block';
var searchUrl = 'AddEnteringApproval_approval';
var params = '';
var elemArray = document.mainForm.elements;
for (var i = 0; i < elemArray.length;i++)
{
var element = elemArray[i];
var elementName= element.name;
if(elementName=='formAction')
continue;
params += '&' + elementName+'='+ encodeURIComponent(element.value);
}
params += '&struts.enableJSONValidation=true&struts.validateOnly=true';
createXmlHttpObject(); // this is my function that prepare ajax
sendRequestPost(http_request,searchUrl,false,params);
postValidation();
}
function postValidation() {
var form = $('#mainForm');
var text = http_request.responseText;
//clear previous validation errors, if any
StrutsUtils.clearValidationErrors(form);
alert(text)
//get errors from response
//var text = request.responseText;
var errorsObject = StrutsUtils.getValidationErrors(text);
//show errors, if any
if(errorsObject.fieldErrors)
{
StrutsUtils.showValidationErrors(form, errorsObject);
}
else
{
//good to go, regular submit
form.submit();
}
}
/* This is one of the functions that doesn't work using the simple theme, so I redefined it.
This can be changed to clear the previous errors, as it does in the commented example
cleaning the errors on divErrors.
As I am just showing the messages with alerts I don't need to clear anything,
but the method still need to be redefined, even if it is empty.
*/
StrutsUtils.clearValidationErrors = function(form, errors) {
//clear the div errors
//$('#divErrors').empty();
}
/* This method is responsible to show the messages.
The original versions works with the xhrml and css-xhtml theme but doesn't work with the simple theme
so I override the method with another implementation that shows the messages using alerts.
You can change the implementation to show the messages as you want,
but as the previous method this has to be redefined.
*/
StrutsUtils.showValidationErrors = function(form, errors) {
if(errors.fieldErrors)
{alert((errors.fieldErrors))
for(var fieldName in errors.fieldErrors)
{
alert("errors.fieldErrors[fieldName] " + errors.fieldErrors[fieldName]);
for(var i = 0; i < errors.fieldErrors[fieldName].length; i++)
{
alert('Field ->' + fieldName + '\nError -> ' + errors.fieldErrors[fieldName][i]);
}
}
}
};
but when i execute the code i get no organized JSON text i showed in alert message box, the field name is not like the one in the error message, the second field name is missing, the third field name is cut (i.e. carrierNo becomes rNo ).
can you help me. i want the field name in the JSON error match the error message text
I just figured out what is the problem, but i don't know why it happens and why.
it always remove the first 6 characters. why this happens
well I figured out the problem.
it was a but in org.apache.struts2.interceptor.validation.JSONValidationInterceptor
it removes the 6 first characters because of this incomplete if statement
sb.append((validationAware instanceof ModelDriven) ? ((String)fieldError.getKey()).substring(6) : (String)fieldError.getKey());
this error is fuond in struts 2.1.8
it should be like this
sb.append(((validationAware instanceof ModelDriven)) && (fieldErrorKey.startsWith("model.")) ? fieldErrorKey.substring(6) : fieldErrorKey);
it was corrected in later struts releses. i corrected the problem. and i thought i have to share the information for people who faces the problem.