I have overridden magento SwatchRenderer.js file in app\code\Mydirectory\CustomSwatches\view\frontend\web\js\SwatchRenderer.js.
My problem is I get an error in my product page load:
Uncaught TypeError: Cannot read property 'updateData' of undefined
I found out that data('gallery') on SwatchRenderer.js's following function is undefined.
updateBaseImage: function (images, context, isProductViewExist) {
var justAnImage = images[0];
if (isProductViewExist) {
context
.find('[data-gallery-role=gallery-placeholder]')
.data('gallery')
.updateData(images);
} else if (justAnImage && justAnImage.img) {
context.find('.product-image-photo').attr('src', justAnImage.img);
}
}
I checked a Magento 2 demo site. On that site the above data attribute is set as a JavaScript object. The target element is a div with the above attribute. But in my site it is undefined and obviously I think that data attribute is not set on my site. Can anyone help me to find the setter function/view/file for above element? Any help would be appreciated. Thanks.
What theme was used in your Magento instance? Did you rename the container class names?
One interesting piece of code is found on line 202 of the SwatchRenderer.js file. Under the _create function you will find the initialization of the gallery variable as seen here
You will notice that it finds the element with the data-gallery under the .column.main element. Thus, as missing column main element would return an empty response.
I found a pretty efficient way to fix this:
Copy the /vendor/magento/module-swatches/view/frontend/web/js/swatch-renderer.js-file to app/design/YourName/YourTheme/Magento_Swatches/web/js/swatch-renderer.js and replace the code inside updateBaseImage() (line ~1152) with the following:
updateBaseImage: function (images, context, isInProductView, eventName) {
var gallery = context.find(this.options.mediaGallerySelector).data('gallery');
if (eventName === undefined && gallery !== undefined) {
this.processUpdateBaseImage(images, context, isInProductView, gallery);
} else {
context.find(this.options.mediaGallerySelector).on('gallery:loaded', function (loadedGallery) {
loadedGallery = context.find(this.options.mediaGallerySelector).data('gallery');
this.processUpdateBaseImage(images, context, isInProductView, loadedGallery);
}.bind(this));
}
},
The trick is: this method doesn't wait for the gallery to be fully loaded, while this event (gallery:loaded) is readily available. By adding this to the method, it works fine.
I just hope that the Magento Dev's pick up on this and implement this in the core-code.
Related
I am trying to change the visibility style of a div element in a svelte component based on a typescript function.
The sample code is like the ones below:
<script>
const abc = () => {
if (RecipientNumberOffScreen == 0) {
return document.querySelector<HTMLElement>('.recipients__OffScreen').style.visibility = 'hidden'
} else {
return RecipientNumberOffScreen // a calculated variable
}
}
</script>
<div class="recipients">
<div class="recipients__OffScreen">{abc()}</div>
</div>
And I am getting the following error in the console
Uncaught TypeError: Cannot read properties of null (reading 'style')
What I could understand by debugging that the document.querySelector<HTMLElement>('.recipients__OffScreen') is getting null value because first the JS gets loaded in the DOM, and then the html codes are being loaded. I was wondering if there is any way to make the function execution wait before the html gets loaded in svelte? Or what is the best way to achieving it?
I am very new to svelte, thanks in advance.
I have a trivia app that is importing an array of objects called "questions". I have used getElementById to capture each of the buttons, and also added click event listeners for the "checkAnswer" function below.
However, I am getting the error: Uncaught TypeError: can't access property "correct", answer is undefined. This happens with any button I click.
I am using type="module" within the script tag in the HTML file.
The buttons are populating the correct text, but are not console logging any text like it should.
"randomQuestion" is a global variable that is being generated in another function within the same file. This is what it looks like:
randomQuestion = questions[Math.floor(Math.random()*questions.length)];
function checkAnswer(bntIndex) {
answer = randomQuestion.answers[bntIndex];
if (answer.correct === true) {
console.log("Correct!");
} else {
console.log("Incorrect");
}
}
It's rather a warning than an error.
You are getting those because you don't export this function and also don't use it anywhere
<full-calendar #unitCalendar [editable]='true' [defaultView]="calendarView" [defaultDate]="unit.start_date*1000" [plugins]="calendarPlugins" [header]="calendarHeader" (eventClick)="viewEventDetails($event)" (eventDrop)='updateDate($event)' (dateClick)="handleDateClick($event)" [eventSources]="calendarEventSource"></full-calendar>
I have tried adding eventAllow as a callback and define a method inside the ts file but the method is never called as if the event is never fired.
I resolved this my self after a frustrating time. The answer is to create a property/variable in the js/ts file titled eventAllow and set the variable to a function with a response type of boolean.
eventAllow = function (dropInfo, draggedEvent) {
if(draggedEvent.extendedProps.calendarEvent.id !== null) {
return true;
}
return false;
}
and read the property/variable in the HTML file like below.
<full-calendar
#unitCalendar
[editable]='true'
[defaultView]="calendarView"
[defaultDate]="unit.start_date*1000"
[plugins]="calendarPlugins"
[header]="calendarHeader"
(eventClick)="viewEventDetails($event)"
(eventDrop)='eventDropped($event)' (eventResize)='eventResized($event)'
[eventAllow]='eventAllow'
(dateClick)="handleDateClick($event)" [eventSources]="calendarEventSource"
></full-calendar>
NOTICE: Creating a method instead of a property/variable will not work and possibly cause a StackOverflow.
Hope this helps anyone out there with a similar issue!
I've a javascript function that has to create graph:
<script>
window.setGraph = (lab, ser) => {
console.log(document.getElementById("weather-chart"));
console.log(lab);
console.log(ser);
var chart = new Chartist.Line('#weather-chart', {
labels: lab,
series: ser
});
console.log("done");
return true;
}
</script>
This function is called by one of my blazor component:
protected override async Task OnInitAsync()
{
some-data-a = await RetrieveSomeData();
some-data-b = await RetrieveSomeOtherData();
JSRuntime.Current.InvokeAsync<bool>("setGraph", some-data-a, some-data-b);
}
Everything is executed, my console.log are called. But it appears that at this moment my element #weather-chart cannot be found, because I get this:
chartist.min.js:8 Uncaught TypeError: Cannot read property 'querySelectorAll' of null
at Object.c.createSvg (chartist.min.js:8)
at f.d [as createChart] (chartist.min.js:8)
at f.h (chartist.min.js:8)
AND
my console.log(document....) is returning null.
If I go to this page, I've the error, and if just after getting this error I do something like window.setGraph([1,2,3], [[1,2,3]]) in my chrome developer tools, everything is initialized correctly.
So what did I do wrong? Why chartist doesn't seems to be able to find the element?
It appears that blazor's databinding was taking some time to display the html. So basically after I set the _items, it was changing the template, but not fast enough for the line after this(not sure why, since there was an await).
I've dug into this for a couple of hours, looking at Javascript prototype accessing another prototype function, Accessing a Javascript prototype function, Trigger one prototype function from another (including itself), Cannot call prototype method from another function and around 3-4 other similar questions, and thought "ok, that doesn't seem so bad" and went to implement a solution (or three) to my particular problem. Or so I had thought!
I have a JS file (compiled from Typescript) that contains an AppComponent class and several methods with it (shortened version focused on my specific trouble follows):
AppComponent = (function () {
function AppComponent() {
var _this = this;
this.gridNo = '1';
//... and so on...
}
AppComponent.prototype.MenuSelect = function (link) {
this.tabCount = 0;
this.tables = [];
utils_1.Logging(' MenuSelect: ' + JSON.stringify(link));
var grids = link.grids;
this.ws.emit('C:GDRDN', { ds: grids });
// build up some HTML to make a table of data and return it to
// the caller
return "grid stuff!";
};
.
.
.
}
The above is loaded up into Angular 2/Node (written by another co-worker) and works just fine in the context it was written: ie it displays tables of data ('grids') when called from other components written by that co-worker in TypeScript.
But when I am generating a menu and try to access the MenuSelect prototype directly from another, 'normal', JS file like so...
function createWHeelNavigation() {
basic.navigateFunction = function () {
var grids_selected = [ 4, 11 ];
var appcomp = new AppComponent();
output = appcomp.MenuSelect(grids_selected);
// minified.js function to add children content to a DOM element
$("grid_container").add(output);
}
// other navigation menu functions...
}
createWHeelNavigation();
...I continue to get "Uncaught ReferenceError: AppComponent is not defined" when I click on that particular 'basic' menu item, even though according to what I've read in SO and elsewhere that creating a 'new' instance of the object is the way to access its prototype methods.
So before I pull my hair out and go back to rocking in the corner of my office, whispering "mommy...", I thought I would pass this around to you fine people to see where I am going wrong. I have a niggling suspicion I should be using 'this' somewhere, but my eyes are crossing, and wish to be pointed in the right direction. Thanks for your time!
I continue to get "Uncaught ReferenceError: AppComponent is not defined" w
A common JavaScript ordering issue. Make sure you are loading your js / ts in the right order.
More
Please use modules if possible. https://basarat.gitbooks.io/typescript/content/docs/tips/outFile.html