K
K
Konstantin Marchenko2018-03-25 21:56:54
Vue.js
Konstantin Marchenko, 2018-03-25 21:56:54

Vue.js - Why does @click only fire once?

Hello! People tell me please. Making modal windows with vue. So there is this html code:

$html ='<div id="app-top">';
         $html .= '<a href="#" @click="zoomModal = true" >Вход</a>';    
                $html .='<modal title="Авторизация" :show.sync="zoomModal" effect="zoom" width="400">
                            <div slot="modal-body" class="modal-body">';
                                $html .= LoginFormWidget::widget([]);
                            $html .='</div>
                        </modal>';            
$html .='</div>';

LoginFormWidget is an authorization form widget, the Activeform form (yii2) is simply inserted there
and, accordingly, the js itself:
// modal component
    Vue.component('modal', {
        template: `              
            <div role="dialog" v-bind:class="{ 'modal':true, 'fade':effect === 'fade', 'zoom':effect === 'zoom' }">
                <div v-bind:class="{'modal-dialog':true,'modal-lg':large,'modal-sm':small}" role="document" v-bind:style="{width: optionalWidth}">
                    <div class="modal-content">
                        <slot name="modal-header">
                            <div class="modal-header">
                                <button type="button" class="close" @click="close"><span>&times;</span></button>
                                <h4 class="modal-title">
                                    <slot name="title">
                                        {{title}}
                                    </slot>
                                </h4>
                            </div>
                        </slot>
                        <slot name="modal-body">
                            <div class="modal-body"></div>
                        </slot>
                        <slot name="modal-footer">
                            <div class="modal-footer">
                                <button type="button" class="btn btn-default" @click="close">{{ cancelText }}</button>
                                <button type="button" class="btn btn-primary" @click="callback">{{ okText }}</button>
                            </div>
                        </slot>
                    </div>
                </div>
            </div>
        `,
        /*data: function data() {
            return {
                zoomModal: false              
            };
          },*/ 
        props: {
            effect: {
                type: String,
                required: true
            },
            large: {
                type: Boolean,                
                default: false
            },
            small: {
                type: Boolean,                
                default: false
            },              
            title: {
                type: String,
                default: ''
            },
            show: {
                required: true,
                type: Boolean,                
                twoWay: false
            },
            cancelText: {
                type: String,
                default: 'Закрыть'
            },
            okText: {
                type: String,
              default: 'Save changes'
            },
            callback: {
                type: Function,
                default: function _default() {}
            },  
            width: {
                default: null
            },  
            backdrop: {
                type: Boolean,                
                default: true
            },     
        },
        computed: {
            optionalWidth: function optionalWidth() {
                if (this.width === null) {
                    return null;
                } else if (jQuery.isNumeric(this.width)) {
                    return this.width + 'px';
                }
                return this.width;
            }
        },
        watch: {
            show: function show(val) {                
                var _this = this;
                var el = this.$el;                
                var body = document.body;  
                              
                if(val) {
                    jQuery(el).find('.modal-content').focus();                    
                    jQuery(el).show();  
                    setTimeout(function(){
                        return jQuery(el).addClass("in");
                    },100); 
                    
                    jQuery(body).addClass("modal-open");
                    
                    if (this.backdrop) {
                        jQuery(el).on('click', function (e) {
                            if (e.target === el) {                                
                                _this.show = false;
                            }
                        });
                    }                    
                } else {
                    jQuery(body).removeClass("modal-open");
                    jQuery(el).removeClass('in').on('transitionend', function () {
                        jQuery(el).off('click transitionend');                        
                        jQuery(el).hide();
                    });      
                    console.log(this);                  
                }    
            
            }
        
        }, 
        methods: {
            close: function close() {                
                this.show = false; 
            }            
        }  
    });

    new Vue({
        el: '#app-top',
        data: {            
            signupShowModal: false,
            zoomModal: false            
        },                
        methods: {            
            getLoginForm() {    
                //var self = this;                   
                //this.zoomModal = true;
            },
            getSignupForm() {                  
                var self = this;
                self.signupShowModal = true;        
            },            
            sendFrom() {                
                this.zoomModal = false;    
            }                             
             
        }        
    });

Everything works great. Clicking on the "Login" link opens a modal window. Further, if you click on the "Close" button to which the method (@click="close") is assigned, then the modal window closes, but then when you click the Login again, the modal window does not open. That is, the click only works once.
I decided to add a link in the LoginFormWidget form and assign its @click="sendFrom" method. In the method itself, I registered the closing of the form:
sendFrom() {                
                this.zoomModal = false;    
            }

That is, when closing the modal window, click not on the Close method, but on the sendFrom method. In this case, the modal window closes and reopens. But why, when closing through the Close method, the window does not open then?!?!

Answer the question

In order to leave comments, you need to log in

2 answer(s)
0
0xD34F, 2018-03-25
@rifer

why when closing through the Close method - the window then does not open?!?!

Opens. If you use vue version 1. In the second, yes - a bummer. What do you have? For some reason I don't think you even thought about it. Well, that is - if it does not work as it should, then the second one, but if the second one then ... What the hell? - you are trying to change a component parameter:
this.show = false;

specify the cut twoWay:
show: {
  required: true,
  type: Boolean,                
  twoWay: false
}

Why doesn't the reopening happen - because you change the value of the parameter inside the component, but outside it doesn't change. That is, from the point of view of the parent component, the modal window remained open. And when you try to open it again, the window state property doesn't change its value, vue doesn't see any changes, and therefore doesn't do anything.
In general - figure out which version of vue you are using. And read the documentation - the root of your problem is that you are trying to use the tool in an unintended way.
UPD. First of all, you should rewrite the work with the show parameter - instead of assigning a value directly, generate an event that you will need to subscribe to in the parent component, and already there change the value of the variable responsible for the visibility of the window (zoomModal, it seems). What exactly is worth reading to understand the problem - one , two .

V
Vladislav Nagorny, 2018-03-25
@esvils

It seems to me that there is a conflict with jquery and vue PS too lazy to analyze the code
If you want both bootsrap and vue use this

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question