1

Based on the code below, I have a varaible mdcDialog, which is initialized with material-components-web (MDCDialog) library once page is loaded.

On form submit, default event is prevented and instead, ajaxSubmit() handle the form.
The response is a json object, from which I can find the variable response.modal.modal with it's string value mdcDialog.

But for one reason or another, console.info(window[response.modal.modal]); return undefined instead of the variable mdcDialog.
On the other hand, doing console.log(mdcDialog) output the variable as it should.

How can I access my variable mdcDialog from a string response if window isn't working?

app.js

/* --- VARS --- */
const page="#page";
let mdcDialog;

/* --- FUNCTIONS --- */
function ajaxSubmit(node) {
    $.ajax({
        type: node.attr("method"),
        url: node.attr("action"),
        enctype: "multipart/form-data",
        data: new FormData(node[0]),
        processData: false,
        contentType: false,
        cache: false
    }).done(function(response, status, xhr) {
        if(response !== false) {
            /** @var response.modal */
            if(typeof response.modal !== "undefined") {
                /** @var response.modal.action */
                /** @var response.modal.modal */
                /** @var response.modal.content */
                if(response.modal.action === "load") {
                    console.info(window[response.modal.modal]);
                }
            }
        }

    }).fail(function(request, status, error) {
        console.error(request);
        console.error(status);
        console.error(error);
    });
}

/* --- ACTIONS --- */
$(document).ready(function() {
    mdcDialog=new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));

    $(page).on("submit", ".ajs", function(e) {
        e.preventDefault();
        ajaxSubmit($(this));
    })
});
FZs
  • 16,581
  • 13
  • 41
  • 50
Preciel
  • 2,666
  • 3
  • 20
  • 45
  • not absolutely certain, but in the browser console, if you enter `console.log(mdcDialog)` does it give you the contents of the variable? otherwise, why not set `window.mdcDialog = new mdc.dialog......` to make sure it's actually in the global scope? I could imagine webpack compiling it into some local scope var. – Jakumi Aug 09 '19 at 16:57
  • yes @Jakumi, if I do `console.log(mdcDialog)`, it gives me the variable. – Preciel Aug 09 '19 at 18:00
  • I have to assume, that you did not enter `console.log(mdcDialog)` *in the browser console* (which would check in the global scope) but instead you put that statement somewhere in the code, where it might access the local scope instead. otherwise, your comment directly contradicts the answer you chose as a solution. – Jakumi Aug 13 '19 at 15:23
  • I use `console.info` most of the time @Jakumi, sorry, I wrote `console.log` above, was my mistake. – Preciel Aug 13 '19 at 16:10
  • I'm not so much worried about log vs info, but more about the place where you put that ... browser console (F12 in most browsers) vs. somewhere in a function – Jakumi Aug 13 '19 at 17:09
  • Ah~ was inside the code, not via the console (F12) itself @Jakumi. My bad, I tends to fly over the text, and have only read the part about doing a console.log. Didn't notice the browser console part. – Preciel Aug 13 '19 at 18:27

3 Answers3

2

You are only defining mdcDialog within the scope of this function (if javascript is running in "Strict Mode"):

$(document).ready(function() {
    mdcDialog=new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));

    ...
});

To give it global scope and make it accessible via window['mdcDialog'] do the following:

$(document).ready(function() {
    window.mdcDialog = new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));

    ...
});

Or define it in the global scope before the function:

var mdcDialog;
$(document).ready(function() {
    mdcDialog = new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));

    ...
});

https://www.w3schools.com/js/js_scope.asp

Arleigh Hix
  • 9,990
  • 1
  • 14
  • 31
  • it's defined in the global scope. 3rd line of my code – Preciel Aug 09 '19 at 21:54
  • Ok, I didn't see that but what happens when you change that line to `window.mcdialog = null;` (no `let`)? – Arleigh Hix Aug 09 '19 at 22:23
  • if I do `window.mdcDialog=new mdc.dialog.MDCDialog(document.querySelector("#dialog-level.mdc-dialog"));` it works, I can read `window['mdcDialog']`. But, it dsoesn't tell me, in my current code, where was set my varaible if it's not in `window` scope by default. My need is to find where my variable is. I got tons of variables in scope, and there is a reason why webpack scope isn't global. – Preciel Aug 12 '19 at 18:16
1

Your app.js file is treated as a JavaScript module which means that variables you declare in it are, by default, scoped to that module and not added to window (which is usually a bad thing to do).

If you want to make something available outside of your module (in another file or from your HTML page / webtools), you can set global.mdcDialog.

That being said I'm not sure what you are trying to do in your example... if you need to access the instance of mdc.dialog.MDCDialog created in the $(document).ready callback, why wouldn't you directly use mdcDialog?

If your use case is "I will have multiple dialogs and will need to retrieve the right one" maybe storing all instances in an object would be a better way to do it:

const dialogs = {};

function ajaxSubmit(node) {
    $.ajax({
        // ...
    }).done(function(response, status, xhr) {
        // ...
        console.info(dialogs[response.modal.modal]);
    });
}

$(document).ready(function() {
    dialogs['mdcDialog'] = new mdc.dialog.MDCDialog(/* ... */);

    $(page).on("submit", ".ajs", function(e) {
        e.preventDefault();
        ajaxSubmit($(this));
    })
});
Lyrkan
  • 1,063
  • 10
  • 18
1

Variables defined with let or const have block scope, and even if they are defined in the outermost scope, they won't be defined globally and therefore will never be accessible through the global (window) object.

To make them accessible that way, you have to use var, or to define them on the global object itself.

let foo=1
window.foo //undefined
foo        //1

var bar=2
window.bar //2
bar        //2

window.baz=3
window.baz //3
baz        //3

See this SO answer for more information

FZs
  • 16,581
  • 13
  • 41
  • 50
  • 1
    I see, that why I can't access it. Thanks for the clarification. – Preciel Aug 13 '19 at 01:19
  • That answer is partially wrong, using `var` won't set it on `window` either since the file is processed by Webpack and treated as a JS module. – Lyrkan Aug 14 '19 at 07:28