1

This is how my code looks like (completely)

function getPassword() {
    let pwd = ($('<input/>', {
   //unrelated code
    })).on('blur', function() {
        //more unrelated code
        } else {
            $(this).css({
                'color': 'gray',
                'border': '1px solid green'
            });
            let cValue = $(this).val();
            console.log(cValue);
            let x = getPasswordConfirm(cValue);
        }
    });
    return pwd;

}

function getPasswordConfirm(cValue) {
    let pwd = ($('<input/>', {
        //more unrelated code
    })).on('blur', function() {
        //unrelated code
        } else {
            if ($(this).val() !== cValue) {
                    console.log(cValue);
//this is where it goes wrong, cValue is undefined???
            } else {
                $(this).css({
                    'color': 'gray',
                    'border': '1px solid green'
                });
                console.log(cValue);
            }
        }
    });
    return pwd;
}

the problem I have is: I use cValue as an argument, yet it doesnt get passed on to my function. When I console.log cValue it returns undefined in my getPasswordConfirm() function. To zoom in on the part where I call the function and try to pass the argument to the parameter:

else {
                $(this).css({
                    'color': 'gray',
                    'border': '1px solid green'
                });
                let cValue = $(this).val();
                console.log(cValue); //this works
                let x = getPasswordConfirm('haha');
            }
        });

and this is the part in my function that should evaluate the current value with the parameter cValue:

 else {
                if ($(this).val() !== cValue) {
                        console.log(cValue); //returns undefined
                } else {
                    $(this).css({
                        'color': 'gray',
                        'border': '1px solid green'
                    });
                    console.log(cValue);
                }

How I append/call the functions:

$(getEblock('col-md-6 col-md-offset-3').append(getLoginName(), getUsrName(), getPassword(), getPasswordConfirm()).appendTo('form'));

but no matter what I use as an argument, it always returns undefined in my getPasswordConfirm(cValue)function. Yes, I do invoke the functions (as you can see).

  • I don't agree with any of the answers below. `cValue` should not be undefined here anyways. There's something wrong with how your logic is implemented, you are making things complicated. You are creating element and binding event on a function call. How many times the functions are called? If multiple times then the code is unpredictable, [see why](https://stackoverflow.com/q/48585165/9276329). Simplify it. – Munim Munna Oct 21 '18 at 00:15
  • Yes, I call the functions so they can be appended to my DIV. So I am calling the function multiple times. –  Oct 21 '18 at 10:11
  • 1
    So, there it is, you are calling `getPasswordConfirm` without any argument. So `cValue` is undefined. Call that with an argument. – Munim Munna Oct 21 '18 at 14:42
  • oke, but how can I give the value of the function password() as an argument to my getPasswordConfirm function? –  Oct 21 '18 at 16:13
  • it indeed works when I call the appended one with an argument, but how do I want to return the value of my function password() so it will be taken over by my confirm function? (I couldnt edit the post any longer since the time was over) –  Oct 21 '18 at 16:28

3 Answers3

1

Please believe me, previous answer was the correct way to go, but if you want to try your own flow, then here is a solution, it will be slower, many unwanted variables, so much coding, etc. you can play with code from jsbin

// declare global
// getting form by id (jquery), 
// it is always good practise to define your element in global scope
// we used $somename for jquery specific names
// remember $('somekelement') is a heavy function of jQuery 
// which did lots of calculation behind the scene
// this is why i am declaring it only once 
// it will help me to not used $('#myform') every time, need to access form 
var $myform = $('#myform');

// for your logic i wanted two extra boolean to check if my password and confirm_password i created or not.
var isPassword = false; // by default not created
var isConfirmPassword = false; // false means not created true means created.

// this is your function that create a input and some logic as per your requirements
function getPassword() {

  if(!isPassword) {
    let pwd = $('<input/>', {
          type:'text',
          name:'password',
         'placeholder':'Password'
       }).on('blur', function() {

          if(false) {
            //more unrelated code
          } else {
            $(this).css({
                'color': 'gray',
                'border': '1px solid green'
            });
            let cValue = $(this).val();

            console.log("Your cValue: "+ cValue); // here you are getting your values right.

            let x = getPasswordConfirm(cValue);   // here you are calling another function that generate another input
          }
        });
      return pwd;
      isPassword = true;
    }
};


// if this function is generating new input, then it must not be called inside of getPassword function, because blur event may occur multiple times and each blur will create new confirm_password fields
// here i think logically not possible, 
// only possible way here is to distribute your coding into two section
// 1st section will build all your dynamic input fields
// 2nd section will validate your inputs.
function getPasswordConfirm(cValue) {
  window.cValue = cValue; // i saved cValue here in global namespace so next time.
    console.log('argument cValue: '+cValue); // wola, you got the value here.

  // but sadly, you didn't have c_pwd yet, so you couldn't be able to fire blur event here.
  // Your blur event will be created but if will fire on out of focus, but next time cValue will not be passed
  // because it will happened only one time or you will have multiple inputs each trying to catch a event before born to the world
  if(!isConfirmPassword) {
    let c_pwd = ($('<input/>', {  // changed name to c_pwd
       type:'text',
       name:'confirm_password',
      'placeholder':'Confirm Password'
    })).on('blur', function() {
      console.log('What was cValue: '+ window.cValue);
        if(false) {
            //unrelated code
        } else {
            if ($(this).val() !== cValue) {
                    console.log('====rock you got cValue here : '+cValue); // getting this value here as well. but problem is that you are getting multiple inputs
                //this is where it goes wrong, cValue is undefined???
            } else {
                $(this).css({
                    'color': 'gray',
                    'border': '1px solid green'
                });
                console.log(cValue);
            }
        }
    }.bind(this)); // you can also bind your subscope to their parent scope by bind funciton, in new ES6 we create arrow function (arg1, arg2) => {console.log(arg1,arg2);}

    isConfirmPassword = true;

    //return c_pwd; // comment this line and uncomment next line see result by yourself. 
    $myform.append(c_pwd); // i am appending confirm_password input on blur on password result will create multiple confirm boxes   
  }
};


$myform.append(getPassword());

// suppose your two function build your form then code for appending will be like that
//$myform.append(getPassword()).append(getPasswordConfirm());
sorabh86
  • 457
  • 4
  • 17
  • 1
    oke, and my question now is: How do I use the cValue as an argument for my parameter in my next function, because THAT ONE returns undefined. –  Oct 19 '18 at 08:09
  • if you are using let keyword then it means variable will only alive within that function, if you use var keyword then it will alive in all sub scopes. you need to declare you cValue in global namespace, like window.cValue = null; then assign there value later in one function and access in another function. – sorabh86 Oct 19 '18 at 08:47
  • 1
    But even with the "var" keyword, it returns undefined. it cannot seem to call the other function. or should the cValue be put at the top of my document –  Oct 19 '18 at 10:58
  • yes it will work fine if you declare in global scope, top of your document. You can check it by declaring a line "use strict"; at the top of your file. now inpect your console, if you try to run it will throw error of undeclared variable accessing. using let keyword will make variable to restricted within a single scope, for more information please have a look about how scoping works . https://www.w3schools.com/js/js_scope.asp – sorabh86 Oct 19 '18 at 12:59
  • please check works fine, i just added wrapper https://jsbin.com/reqigid/edit?html,js,output – sorabh86 Oct 20 '18 at 19:20
  • 1
    Yes, the JS solution worked, but how would you do it with Jquery –  Oct 21 '18 at 10:11
  • looks like you are creating a dynamic form generation, by using jquery. could you give up vote for all my comment? it may unlock some feature in this site. i will create a little script for you in jsbin sooner. if you asked me, how i do validate my form fields then i do use jquery.validate.js library. because i don't want code again and again specially for things already available. and focus more over learning new things & data structure, oops concepts, networking architecture, an now popular artificial intelligence attracting me so much. – sorabh86 Oct 21 '18 at 16:12
0

The problem is that you create an eventhandler INSIDE your function (which you shouldn't, if you call the function more than once, but that's another story). By the time you create the handler, 'cValue' IS defined. But after you have have created the handler, the function exits (it has done it's Work). Then when the event occurs 'cValue' is no longer defined (since the outer function has long finished and cValue is garbage collected.

The solution to the problem could be that the outer function stores the value of cValue in a global variable. Then when the event occurs, grap this global variable insdie the eventhandler and use it.

Poul Bak
  • 10,450
  • 5
  • 32
  • 57
  • I reckon you've got this spot on. `cValue` is defined at event creation time but then that value is lost. If the creator of this question wants `cValue` to be reusable when `blur` events are fired, they're going to have to ensure that the value which is stored in `cValue` is stored in a global variable. – AJC24 Oct 20 '18 at 16:55
0

I would suggest keeping a loosely coupled structure what you are trying to do. So I suggest to pass a context to all methods to keep track and interact. You can also use this context for accumulating form-data or other purpose later if needed.

let context = {}
$(getEblock('col-md-6 col-md-offset-3').append(
  getLoginName(context),
  getUsrName(context),
  getPassword(context),
  getPasswordConfirm(context)
).appendTo('form'));

function getPassword(context) {
  let pwd = ($('<input/>', {
    //unrelated code
  }))
  .on('blur', function() {
    //more unrelated code
    context.cValue = $(this).val();
  });
  return pwd;
}

function getPasswordConfirm(context) {
  let pwd = ($('<input/>', {
    //more unrelated code
  }))
  .on('blur', function() {
    if ($(this).val() !== context.cValue) {
      //password mismatch
    }
  });
  return pwd;
}
Munim Munna
  • 17,178
  • 6
  • 29
  • 58