codernoob5
codernoob5

Reputation: 121

vuejs hide modal when click off of it

Hey guys I have a form in a vuejs component that looks like this (I realize theres a lot of code here but the important thing to worry about is the shade class):

<script>Vue.component('profileinfo', {
  template: `<div><div id="profileInfo">
        <div class="sectionHeader">Profile</div>
        <div class="dataPoint">First:&nbsp;{{firstNameBraintree}}</div>
        <div class="dataPoint">Last:&nbsp;{{lastNameBraintree}}</div>
        <div class="dataPoint">Company:&nbsp;{{companyBraintree}}</div>
        <div class="dataPoint">Email:&nbsp;{{emailBraintree}}</div>
        <div class="dataPoint">Phone:&nbsp;{{phoneBraintree}}</div>
        <div class="buttonDiv">
            <input class="button" type="button" value="Update" v-on:click="showUpdateProfileForm()">
        </div>
      </div>
<!--Show Update Profile Form-->
<div style="display:none;" v-cloak v-show="showupdateprofileinfoform==true" class="shade"></div>
<div style="display:none;" v-cloak class="updateProfileForm" v-show="showupdateprofileinfoform==true">

      <h2>Update Account Information</h2>
            <h2>Username: <?php echo $_SESSION['username'];?></h2>
      <!--PASSWORD-->
      <div class="inputDiv">
      <p v-show="passwordLengthMet==true && passwordHasCap==true && passwordHasNum==true || password.length=='' && passwordHasCap==false && passwordHasNum==false">Password * <i class="fa fa-check-circle success"></i> Valid</p>
          <p v-show="passwordLengthMet==false && password.length!='' || passwordLengthMet==true && passwordHasCap==false || passwordLengthMet==true && passwordHasNum==false">Password * <i class="fa fa-exclamation-circle tooltip error"><span class="tooltiptext">Password must be at least 8 characters, Have a capital letter and contain a number</span></i></p>
       <input type="password" v-model="password" placeholder="********" v-on:focus="showpasswordrequirements">
         <ul v-show="dispassr==true">
          <li v-show="passwordLengthMet==false || password==''">Must contain at least 8 characters</li>
             <li v-show="passwordHasCap==false">Must contain capital letter</li>
             <li v-show="passwordHasNum==false">Must contain number</li>
        </ul>
    </div>
      <!--END PASSWORD-->

      <!--PASSWORDS MATCH-->
    <div class="inputDiv">
      <p v-show="passwordsMatch==true">Confirm Password* <i class="fa fa-check-circle success"></i> Passwords Match</p>
         <p v-show="passwordsMatch==false">Confirm Password* <i class="fa fa-exclamation-circle tooltip error"><span class="tooltiptext">Please make sure passwords match</span></i></p>
     <input type="password" v-model="confirmPassword" placeholder="********" v-on:focus="showconfirmpasswordrequirements">
        <ul v-show="disconfr==true">
        <li class="blue" v-show="passwordsMatch==false || confirmPassword==''">Please be sure your passwords match</li>
        </ul>
    </div>
      <!--END PASSWORDS MATCH-->

      <!--FIRSTNAME-->
    <div class="inputDiv">
      <p v-show="validFirstname==true">First name* <i class="fa fa-check-circle success"></i> Valid</p>
      <p v-show="validFirstname==false && sub==1">First Name* <i class="fa fa-exclamation-circle tooltip error"><span class="tooltiptext">Please enter your firstname</span></i></p>
        <p v-show='validFirstname==false && sub!="1"'>First Name* <i class="fa fa-question-circle tooltip" style="color:darkblue;"><span class="tooltiptext blue" style="background-color:darkblue;">Please enter a firstname</span></i></p>
        <input v-model="firstName" placeholder="Firstname" v-on:focus="showfirstnamerequirements">
        <ul v-show='disfnamer==true'>
        <li v-show="validFirstname==false">Please enter a firstname</li>
        </ul>
    </div>
      <!--END FISTNAME-->

      <!--LASTNAME-->
    <div class="inputDiv">
      <p v-show="validLastname==true">Last Name* <i class="fa fa-check-circle success"></i> Valid</p>
      <p v-show="validLastname==false && sub==1">Last Name* <i class="fa fa-exclamation-circle tooltip error"><span class="tooltiptext">Please enter your lastname</span></i></p>
        <p v-show='validLastname==false && sub!="1"'>Last Name* <i class="fa fa-question-circle tooltip" style="color:darkblue;"><span class="tooltiptext blue" style="background-color:darkblue;">Please enter a lastname</span></i></p>
        <input v-model="lastName" placeholder="Last name" v-on:focus="showlastnamerequirements">
        <ul v-show='dislnamer==true'>
        <li v-show="validLastname==false">Please enter a lastname</li>
        </ul>
    </div>
      <!--END LASTNAME-->

      <!--EMAIL-->
    <div class="inputDiv">
        <p v-show="validEmail==true">Email* <i class="fa fa-check-circle success"></i> Valid</p>
        <p v-show="validEmail==false && email!=='' || email=='' && sub==1">Email* <i class="fa fa-exclamation-circle tooltip error"><span class="tooltiptext">Please enter a valid email</span></i></p>
        <p v-show="email=='' && sub==0">Email* <i class="fa fa-question-circle tooltip" style="color:darkblue;"><span class="tooltiptext blue" style="background-color:darkblue;">Please enter a valid email</span></i></p>
      <input v-model="email" placeholder="[email protected]" v-on:focus="showemailrequirements">
        <ul v-show='disemailr==true'>
        <li v-show="validEmail==false">Please enter a valid email</li>
        </ul>
      </div>
        <!--END EMAIL-->

        <!--PHONE -->
        <div class="inputDiv">
        <p v-show="phoneLength==true && phoneHasNum==true && phoneNumber!=''">Phone* <i class="fa fa-check-circle success"></i> Valid</p>
        <p v-show="phoneLength==false && phoneNumber!='' || phoneHasNum==false && phoneNumber!='' || phoneNumber=='' && sub==1">Phone* <i class="fa fa-exclamation-circle tooltip error"><span class="tooltiptext">Phone Number must have at least 10 numbers and have no letters, parenthis or dashes</span></i></p>
        <p v-show="phoneNumber=='' && sub==0">Phone* <i class="fa fa-question-circle tooltip" style="color:darkblue;"><span class="tooltiptext blue" style="background-color:darkblue;">Phone Number must have at least 10 numbers and have no letters it cannot contain parenthis or dashes</span></i></p>
        <input v-model="phoneNumber" placeholder="Phone Number 1234567890" v-on:focus="showphonenumberrequirements" id="phoneNumber">
        <ul v-show="disphoner==true">
        <li v-show="phoneLength==false">Phone number must be 10 numbers long</li>
        <li v-show="phoneHasNum==false || phoneNumber==''"> Phone number must contain only numbers</li>
        </ul>
      </div>
        <!--END PHONE-->

        <!--COMPANY NAME-->
        <div class="inputDiv">
            <p v-show="validCompanyName==true">Company Name* <i class="fa fa-check-circle success"></i> Valid</p>
            <p v-show="validCompanyName==false && companyName!='' || companyName==false && companyName=='' && sub==1">Company Name* <i class="fa fa-exclamation-circle tooltip error"><span class="tooltiptext">Please enter your company name</span></i></p>
            <p v-show="companyName=='' && sub==0">Company Name*  <i class="fa fa-question-circle tooltip" style="color:darkblue;"><span class="tooltiptext blue" style="background-color:darkblue;">Please enter your company name</span></i></p>
            <input v-model="companyName" placeholder="Company Name" v-on:focus="showcompanynamerequirements">
            <ul v-show="discompr==true">
            <li v-show="validCompanyName==false">Please enter your company name</li>
            </ul>
      </div>
        <!--END COMPANY NAME-->

       <div class="inputDiv">
                <div class="sliderWrapper">
                    <div><strong>Subscribe to Email List</strong></div>
            <label class="switch">
                <input type="checkbox" v-model="subscribe" value="1">
                <span class="slider"></span>
            </label>
        </div>
      </div>
    <div class="inputButton">
      <input v-on:click="updateAccount()" type="button" class="saveProfileButton" value="Update">
    </div>
    <div class="inputButton">
          <input v-on:click="hideUpdateProfileForm()" type="button" class="cancelProfileButton" value="Cancel">
    </div>
  </div>
<!--End Update Profile Form--></div>`,
  data() {
    return {
    showSpinner: false,
    showupdateprofileinfoform: false,
    password: '',
    confirmPassword: '',
    firstName: '',
    lastName: '',
    email: '',
    sub: '',
    subscribe:'',
    dispassr: '',
    disconfr: '',
    disfnamer: '',
    dislnamer: '',
    disemailr: '',
    disphoner: '',
    discompr: '',
    phoneNumber: '',
    companyName: '',
     customerId: '<?php echo $customer->id; ?>',
    companyBraintree:'<?php echo $customer->company; ?>',
    firstNameBraintree:'<?php echo $customer->firstName; ?>',
    lastNameBraintree:'<?php echo $customer->lastName; ?>',
    phoneBraintree:'<?php echo $customer->phone; ?>',
    emailBraintree:'<?php echo $customer->email; ?>',
    phone:'',
    updated: ''
    }
  },
    computed: {
    passwordsMatch: function() {
        this.confirmPassword=this.confirmPassword.replace(/\s/g, '');
      if(this.password == this.confirmPassword) {
        return true;
      } else {
        return false;
      }
    },
    passwordLengthMet: function() {
        this.password=this.password.replace(/\s/g, '');
      if(this.password.trim().length >0 && this.password.trim().length >= 8) {
        return true;
      } else {
        return false;
      }
    },
    passwordHasCap: function(){
      if(/[A-Z]/.test(this.password)){return true;} else{return false;}         
    },
    passwordHasNum: function(){
      if(/[\d]/.test(this.password)){return true;} else{return false;}  
    },
    validEmail: function() {
        this.email=this.email.replace(/\s/g, '');
      var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
      if (!reg.test(this.email)) {
        return false;
      }
      return true;
    },
      validLastname: function() {
          this.lastName=this.lastName.replace(/\s/g, '');
          if(this.lastName.trim().length<1){return false;} else {return true;}
      },
      validFirstname: function() {
          this.firstName=this.firstName.replace(/\s/g, '');
       if(this.firstName.trim().length<1){return false;} else{return true;}   
      },
      validCompanyName: function(){
          if(this.companyName.trim().length<1){return false;} else{return true;}
      },
      phoneHasNum: function(){
          if(isNaN(this.phoneNumber)){return false;} else {return true;}
      },
      phoneLength: function(){
          this.phoneNumber=this.phoneNumber.replace(/[^0-9]+/g, '');
          if(this.phoneNumber.trim().length==10){return true;} else{return false;}
      }
  },
    created: function() {
      this.subscribe=1;
      this.firstName='<?php if(isset($_SESSION['firstname'])){echo $_SESSION['firstname'];}?>';
      this.lastName='<?php if(isset($_SESSION['lastname'])){echo $_SESSION['lastname'];}?>';
      this.email='<?php if(isset($_SESSION['email'])){echo $_SESSION['email'];}?>';
      this.companyName='<?php if(isset($_SESSION['companyname'])){echo $_SESSION['companyname'];}?>';
      this.phoneNumber='<?php if(isset($_SESSION['phonenumber'])){echo $_SESSION['phonenumber'];}?>';
  },
  methods: {
  showUpdateProfileForm: function(){
      this.showupdateprofileinfoform=true;
  },
  hideUpdateProfileForm: function(){
  this.showupdateprofileinfoform=false;
},
    updateAccount: function() {
        this.sub=1;
      if(this.validFirstname && this.validLastname && this.validEmail && this.passwordsMatch && this.validCompanyName && this.phoneHasNum && this.firstName!='' && this.lastName!='' && this.email!='' && this.phoneNumber!='' && this.companyName!='' && this.passwordLengthMet && this.passwordHasNum && this.passwordHasCap && this.password!='' && this.confirmPassword!='' || this.validFirstname && this.validLastname && this.validEmail && this.passwordsMatch && this.validCompanyName && this.phoneHasNum && this.firstName!='' && this.lastName!='' && this.email!='' && this.phoneNumber!='' && this.companyName!='' && this.password=='' && this.confirmPassword=='') {
        var jsonString = JSON.stringify({
          firstName: this.firstName,
          lastName: this.lastName,
          password: this.password,
          email: this.email,
          phoneNumber: this.phoneNumber,
          companyName: this.companyName,
          subscribe: this.subscribe
        });

        $.ajax({
          url: 'updateAccountInfoBackend.php',
          dataType: 'json',
          type: 'post',
          contentType: 'application/json',
          dataType: 'json',
          data: jsonString,
            error: function(data){
              alert('error');
//                window.location.href='successfullycreated.php';
            },
          success: function(data){
            console.log(data);
              alert('success');
              if(data.updated==1){location.reload();}
              if(data.updated==0){location.reload();}
          }.bind(this)
        });
    }
    },
      showpasswordrequirements: function(){
          this.sub=0;
          this.dispassr=true;
          this.disconfr=false;
          this.disfnamer=false;
          this.dislnamer=false;
          this.disemailr=false;
          this.disphoner=false;
          this.discompr=false;
      },
      showconfirmpasswordrequirements: function(){
          this.sub=0;
          this.dispassr=false;
          this.disconfr=true;
          this.disfnamer=false;
          this.dislnamer=false;
          this.disemailr=false;
          this.disphoner=false;
          this.discompr=false;
      },
      showfirstnamerequirements: function(){
          this.sub=0;
          this.dispassr=false;
          this.disconfr=false;
          this.disfnamer=true;
          this.dislnamer=false;
          this.disemailr=false;
          this.disphoner=false;
          this.discompr=false;
      },
      showlastnamerequirements: function(){
          this.sub=0;
          this.dispassr=false;
          this.disconfr=false;
          this.disfnamer=false;
          this.dislnamer=true;
          this.disemailr=false;
          this.disphoner=false;
          this.discompr=false;
      },
      showemailrequirements: function(){
          this.sub=0;
          this.dispassr=false;
          this.disconfr=false;
          this.disfnamer=false;
          this.dislnamer=false;
          this.disemailr=true;
          this.disphoner=false;
          this.discompr=false;
      }, 
      showphonenumberrequirements: function(){
          this.sub=0;
          this.disphoner=true;
           this.dispassr=false;
          this.disconfr=false;
          this.disfnamer=false;
          this.dislnamer=false;
          this.disemailr=false;
          this.discompr=false;
    },
      showcompanynamerequirements: function(){
          this.sub=0;
          this.disphoner=false;
           this.dispassr=false;
          this.disconfr=false;
          this.disfnamer=false;
          this.dislnamer=false;
          this.disemailr=false;
          this.discompr=true;
      }
  }
});

This component is than included in the following vueapp:

<?php session_start(); ob_start();
if(!isset($_SESSION['username'])){header('Location:logout.php');}
  require_once 'lib/Braintree.php';
  require_once('head.php');
  require_once('header.php');

  $gateway = new Braintree_Gateway([
    'environment' => 'sandbox',
    'merchantId' => 'key',
    'publicKey' => 'key',
    'privateKey' => 'key'
  ]);

  $customer = $gateway->customer()->find($id);
  $plans = $gateway->plan()->all();

  $plansArray = array();

  foreach ($plans as $plan) {
    array_push($plansArray, $plan);
  }

  $subscriptions = array();

  foreach ($customer->creditCards as $card) {
    foreach ($card->subscriptions as $subscription) {
      array_push($subscriptions, $subscription);
    }
  }
?>
<script src="vue.js"></script>
  <script src="jquery-3.3.1.js"></script>
  <?php include('components.php');?>
</head>
<body>
  <div id="app">
    <div id="profileContainer">
    <profileinfo></profileinfo>
 </div>
      </div>
 <script>
        var app=new Vue({
        el:'#app',
        data:{  
        },
        });
  </script>
<?php include('foot.php');?>
</body>
</html>

I have the component popping up in a modal and the background is shaded.

However when they click off the modal I want it to run a function that would make it disappear. Lastly heres the css for the class of shade and updateProfileForm:

.updateProfileForm{
  box-shadow: 1px 5px 20px -2px rgba(0,0,0,0.2);
  width: 500px;
  height: auto;
  position: fixed;
  background-color: white;
  top: 90px;
  left: 50%;
  margin-left: -265px;
  z-index: 100;
  padding: 30px 0 0 30px;
}
.shade {
position: fixed;
background-color: black;
top: 0;
left: 0;
height: 100%;
width: 100%;
opacity: 0.5;
z-index: 99;
}

Upvotes: 2

Views: 5334

Answers (1)

Daniel
Daniel

Reputation: 35684

That's a lot of code to look through, it might make for better answers if you can post things limited to relevant parts, or have working code either embedded or linked to jsfiddle.

Anyway, what you can do is have the "shade" part of your modal, that way you can manage the state and functionality from the same component. Also using a separate reusable modal component may help (but not needed)

here is a slightly modified version of what is on official vue example page https://v2.vuejs.org/v2/examples/modal.html

I've changed line 5 <div class="modal-wrapper" @click="$emit('close')">

and line 6 <div class="modal-container" @click.stop="">

line @click.stop="" is required to prevent propagation of the modal content, which is an issue as @nuts pointed out.

https://jsfiddle.net/zkmd64b3/

this example uses slots for extension, but you can do the same without it by calling the same function on close action as on click for the modal-wrapper

Upvotes: 7

Related Questions