Set input field value in panel from js

Hello,

I want to set value from js. When one field changes, I want to update another value, that user would have “helper” for his next datadield.

My code is:

(function () {
	window.addEventListener('keyup', function(){
		if (document.activeElement.name === 'personal_code') {

				var $ak = document.activeElement.value;
				if (($ak || '').length === 11) {
					var birthdayElement = document.getElementsByName('birthday')[0];

					var $A = $ak[0];
					//birthdayElement.focus(); // not helps
					if ($A > 0) {
						$year = 1900 + Math.floor(($A - 1) / 2) * 50;
						birthdayElement.value = Math.floor($year / 100) + $ak[1] + $ak[2] + ' ' + $ak[3] + $ak[4] + ' ' + $ak[5] + $ak[6];
					} else
						birthdayElement.value = $ak[1] + $ak[2] + ' ' + $ak[3] + $ak[4] + ' ' + $ak[5] + $ak[6];
					//birthdayElement.blur(); // not helps
				}

		}
	});
})();

But after value changes, system still sees it as blank. What I’m doing wrong?

The panel is built upon Vue 2. That’s a “Model–view–viewmodel” framework. This means the data isn’t directly stored in the input elements, but instead in a “model” that is “bound” to those elements. This means you can’t just set the .value property of Kirby’s form elements and expect it to work. You’d have to update the “model” instead. Vue will then take care of updating the corresponding form inputs.

Kirby exposes some hooks that people use to create panel plugins, but your usecase, and for example this other one isn’t a supported one. People normally skip form fields whose value can be derived from other values:
E.g: if the birthdate can always be calculated from the personal code, there isn’t much of a reason in having the field at all. A page model would probably be better suited.
If you need this feature you could either create a custom field, or hack something together like the following plugin (hoping that in the future the kirby internals don’t change too much):

(function() {
let initialized = false;

function codeToBirthday(code) {
  const A = parseInt(code[0]);
  if(A > 0) {
    const year = 1900 + Math.floor((A - 1) / 2) * 50;
    return Math.floor(year / 100) + code[1] + code[2] + ' ' + code[3] + code[4] + ' ' + code[5] + code[6];
  } else {
    return code[1] + code[2] + ' ' + code[3] + code[4] + ' ' + code[5] + code[6];
  }
}

panel.plugin('mantas/pluginname', {
  use: [
    function(Vue) {
      Vue.mixin({
        created: function() {
          if (!initialized && this.$events && !this.$parent) {
            //we want this to run only once
            initialized = true; 

            //the store contains all the data
            const store = this.$store 

            //when content in the store changes...
            store.subscribe(function(mutation) {
              //check if the change is related to the personal code
              if (mutation.type === 'content/UPDATE' 
                && mutation.payload[1] === 'personal_code') {

                const code = mutation.payload[2];
                //if the new code is 11 digits long, we can assume it's a valid code
                if(code.length === 11) {
                  //calculate the birthday
                  const birthday = codeToBirthday(code);
                  
                  //set the birthday in the store
                  store.commit('content/UPDATE', [
                    mutation.payload[0],
                    'birthday',
                    birthday
                  ]);
                }
              }
            })
          }
        }
      });
    }
  ]
});


})();

1 Like

Thank you! Now I see where I was doing wrong.