requirejs defining modules not working as expected - javascript

i have the following scenario:
i have a global namespace called fort which has a few common functions that i need and it looks like this :
fort.js
define("fort", ["fortHistory"], function (FortHistory) {
function Fort(){}
Fort.prototype.history = FortHistory;
return Fort;
});
fortHistory is a small module i created defined as so:
fortHistory.js
"use strict";
define("fortHistory", function () {
function FortHistory() {
}
FortHistory.prototype.doSomething = function(){...}
return FortHistory;
});
i then do this in my config.js
require.config( {
enforceDefine: true,
paths: {
'fort': 'develop/js/fort',
'fortHistory' : 'develop/js/webapp/fortHistory'
},
shim: {
fort:{
exports: 'fort'
}
}
} );
define( function() {} );
finally in main.js i have:
define('fort', [], function(fort){
window.fort = fort;
});
the hope was that i could then make a call such as :
fort.fortHistory.doSomething();
instead fort is undefined so i am assuming i have misinterpreted how requirejs works

You've named it history, not fortHistory:
Fort.prototype.history = FortHistory;
Try calling it via fort.history.doSomething();.

Related

How to override third party module Js widget in custom module in magento 2

Here i'm trying to extend Amasty js widget in my module using mixin.
I have created requirejs-config.js file like below
var config = {
config: {
mixins: {
'amShopbyAjax': {
'vendor_CustomCatalog/js/amasty/amShopbyAjax-override': true
}
}
}
};
I have created js file like below
define([
"jquery",
"jquery-ui-modules/widget"
], function ($) {
'use strict';
var amShopbyWidgetMixin = {
selectors: {
category_products_wrapper: '#amasty-shopby-category-product-list',
},
reloadHtml: function (data) {
console.log("Sdfsdfsdf");
return this._super();
},
callAjax: function (clearUrl, data, pushState, cacheKey, isSorting) {
console.log("sdnjkasndnsadj");
return this._super();
}
};
return function (targetWidget) {
$.widget('custom.amShopbyAjax', targetWidget, amShopbyWidgetMixin);
return $.custom.amShopbyAjax;
};
});
After that I ran sudo bin/magento setup:static-content:deploy -f and clear cache then I am getting "Uncaught TypeError: base is not a constructor" error
Think that you should change custom.amShopbyAjax to mage.amShopbyAjax
return function (targetWidget) {
$.widget('mage.amShopbyAjax', targetWidget, amShopbyWidgetMixin);
return $.mage.amShopbyAjax;
};
The widget alias should be like for the target widget and the widget by parent alias should be returned

Magento2 - Can't access RequireJS dependencies in certain function of overridden JS file

I'm working on Magento 2.1.7 and I'm facing a weird problem in my custom module.
I want to override Magento_Checkout/js/model/shipping-save-processor/default.
I created a requirejs-config.js like this :
var config = {
"map": {
"*": {
"Magento_Checkout/js/model/shipping-save-processor/default" : "<my_vendor>/js/shipping-save-processor/default-override"
}
}
};
and the default-override.js like this :
define(
[
'jquery',
'underscore',
'ko',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/resource-url-manager',
'mage/storage',
'Magento_Checkout/js/model/payment-service',
'Magento_Checkout/js/model/payment/method-converter',
'Magento_Checkout/js/model/error-processor',
'Magento_Checkout/js/model/full-screen-loader',
'Magento_Checkout/js/action/select-billing-address'
],
function ($,
_,
ko,
quote,
resourceUrlManager,
storage,
paymentService,
methodConverter,
errorProcessor,
fullScreenLoader,
selectBillingAddressAction) {
'use strict';
return {
functionA: function () {
console.log(resourceUrlManager); //good => return object with all the function defined in the file Magento_Checkout/js/model/resource-url-manager.js
this.functionB();
},
functionB: function () {
console.log(resourceUrlManager); // fail => Uncaught ReferenceError: resourceUrlManager is not defined
}
};
});
I'm wondering why the dependency injection "works" only for my functionA and not in functionB when its called from functionA and how to solve it cleanly without passing resourceUrlManager by parameter to functionB.
Thank you for your help.

Load standard javascript files with requireJS

I'm trying out requireJS in order to improve the loading of Javascript on an ASP.NET MVC app, using Knockout.
I have some files defining custom ko bindings like that:
(function (ko, bindings) {
bindings.stopBinding = {
init: function () {
return { controlsDescendantBindings: false };
}
};
bindings.anotherBinding = { ... };
})(ko, ko.bindingHandlers);
If I try to load it as a requireJS module this way:
define(['jquery', 'knockout', 'custom/knockout.bindings'], function ($, ko){
ko.applyBindings(...);
});
I get a ko is not defined error.
I know that I could enclose this file in a require callback for instance in order ot make it work:
require(['knockout'], function (ko) {
(function (ko, bindings) {
bindings.stopBinding = {
init: function () {
return { controlsDescendantBindings: false };
}
};
bindings.anotherBinding = { ... };
})(ko, ko.bindingHandlers);
});
Is there another way to allow this file to work without having to update each and every legacy JS file in the application ? I thought of using shim, but I didn't get anywhere, but I'm quite a noob with requireJS, so maybe I'm missing something obvious.
Thanks to this answer, I managed to inject Knockout back in the global namespace, making it available to legacy Javascript files that needed it.
First, create a module that injects ko in the global namespace:
define('knockout.inject', ['knockout'], function (k) {
window.ko = k;
return k;
});
Then, map the module to knockout to execute it for every knockout dependency.
var require = {
baseUrl: "/Scripts",
paths: {
//...
"knockout": "knockout-3.3.0.debug",
"knockoutbindings": "knockout.bindings",
},
shim: {
"knockoutbindings": {
deps: ["knockout"]
}
},
map: {
// inject ko back in the global namespace
'*': {
'knockout': 'knockout.inject'
},
// prevent cycles
'knockout.inject': { 'knockout': 'knockout' }
}
};

failing to fetch method requireJS

I am experiencing some strange issue. I have this
require({
paths: {
'template': 'tmpl.min',
'videoupload.widget': 'jquery.ui.videoupload'
}
}, ['js/main_video.js'], function(App) {
App.initial_video_upload();
});
and this
define(['template','videoupload.widget'],function() {
function initial_video_upload(){
'use strict';
$('#videoupload').videoupload({
//...some code
});
}
return{
initial_video_upload: initial_video_upload
}
}
);
in the file jquery.ui.videoupload.js, I have some call to a tmpl method which is defined in tmpl.min.js, but I get the message
Uncaught TypeError: Object [object Object] has no method 'tmpl'
There are two issues here:
Your first snippet is passing configuration options to a require function. require, is a way to load dependencies and execute some code using them. If you want to pass configuration options to require.js, requirejs.config is what you want:
// configurations to be used in your module definitions
requirejs.config({
paths: {
'template': 'tmpl.min',
'videoupload.widget': 'jquery.ui.videoupload'
}
});
// load your main module and kick things off
require(['js/main_video.js'], function(App) {
App.initial_video_upload();
});)
Your second snippet is declaring dependencies, but not passing them into the callback:
define(['template','videoupload.widget'],
// these are now accessible within the function's scope:
function(template, videoupload.widget) {
function initial_video_upload(){
'use strict';
$('#videoupload').videoupload({
//...some code
});
}
return{
initial_video_upload: initial_video_upload
}
}
);
Additionally, I'm assuming jQuery is a dependency of your videoupload.widget. How are you loading that? You may need to add an additional "shim" configuration to your requirejs.config:
requirejs.config({
paths: {
'template': 'tmpl.min',
'videoupload.widget': 'jquery.ui.videoupload'
},
shim: {
"videoupload.widdget": ["jquery"]
}
});

How to load koLite with requirejs?

This is from knockout.dirtyFlag.js
;(function (ko) {
ko.DirtyFlag = function (objectToTrack, isInitiallyDirty, hashFunction) {
hashFunction = hashFunction || ko.toJSON;
var
_objectToTrack = objectToTrack,
_lastCleanState = ko.observable(hashFunction(_objectToTrack)),
_isInitiallyDirty = ko.observable(isInitiallyDirty),
result = function () {
var self = this;
self.isDirty = ko.computed(function () {
return _isInitiallyDirty() || hashFunction(_objectToTrack) !== _lastCleanState();
});
self.reset = function () {
_lastCleanState(hashFunction(_objectToTrack));
_isInitiallyDirty(false);
};
return self;
};
return result;
};
})(ko);
In my model I have a define setup like this:
define([
"lib/knockout",
"lib/knockout.dirtyFlag"
],
function(ko) {
...
self.dirtyFlag = new ko.DirtyFlag([
}
basically I get an error saying that DirtyFlag is undefined.
What do I need to do?
Well, looks like I got it working, so I'll post my findings:
In my requirejs config I added this:
shim: {
"lib/knockout/knockout.dirtyFlag": {
deps: [
"lib/knockout/knockout"
],
init: function (ko) {
var self = this;
ko.DirtyFlag = self.ko.DirtyFlag;
return ko;
}
}
I'm not very familiar with javascript or requirejs, but init seems to put the dep in "ko" and then I am able to create a DirtyFlag on ko. self.ko.DirtyFlag is the actual knockout.dirtyFlag javascript.
You are requiring lib/knockout and lib/knockout.dirtyFlag. Do you need both ?
If you need both, try:
define([
"lib/knockout",
"lib/knockout.dirtyFlag"
],
function(ko, kodf) {
...
self.dirtyFlag = new kodf.DirtyFlag([
}
You could also try:
define([
"lib/knockout",
"lib/knockout.dirtyFlag"
],
function(k) {
...
self.dirtyFlag = new ko.DirtyFlag([
}
As I think you are defining ko in the require as well as in knockout.dirtyFlag.
I have ended with wrapping kolite classes with define methods. Below example with command, but it will be same for others.
requirejs.config({
paths: {
knockout: 'Scripts/libs/knockout/knockout-2.2.1.debug',
command: 'Scripts/libs/knockout/knockout.command'
},
shim: {
knockout: {
exports: 'ko'
},
command: {
deps: ['knockout'],
exports: 'ko'
}
});
And wrapped command
define(['knockout'], function(ko) {
... // command original code
return ko;
)
in my module
define(['command'], function (ko) {
var doYourStaff = 0;
return doYourStaff;
});
We have added support for RequireJS for all three libs now, you can use the latest version from master.

Categories