Issue #2445💬 RespondidoAbierto el 6 de diciembre de 2019por kickbkReacciones 1

Datetimepicker en un nuevo componente

Respuesta rápidapor artf1

La mayor parte de la lógica que haces en 'handleDateInputsOptions' debería estar dentro de tu 'script' de componentes. Tu prop 'dateInputsSelect' contiene el tipo de entrada, así que usa la interpolación en tu 'script' y luego aplica la lógica de 'handleDateInputsOptions'. Otro truco que necesitarías es activar la act...

Lee la respuesta completa abajo ↓

Pregunta

¡Disculpa la extensión de esta pregunta! Es un componente completamente nuevo y ya casi lo he terminado, solo necesito un poco de ayuda y creo que esto podría ser útil para otros.

Estoy creando una entrada de selección de fecha que utiliza la lib de daterangepicker. '''gatherDateOptions()''' recopila todos los campos de tipo de fecha a través de las opciones. Tengo los campos de '''fecha''', 'hora de cita''', ''intervalo' y ''intervalo'''. Luego uso su nombre y divido en "-" para obtener el tipo de campo.

Cargo los scripts uno a uno para evitar problemas de dependencias (como "$ no está definido"). Si crees que hay una forma más eficiente de hacerlo, por favor aconsejadme. Una vez cargado ''daterangepicker', puedo ejecutar la función '''initDateRange''' y, de hecho, ejecutará '''daterangepicker' en el campo y generará el desplegable de selección de fecha en el lugar correcto (bajo el campo de entrada), pero explicaré más adelante por qué esto parece un desperdicio.

Como tengo un select que permite cambiar entre campos y su tipo, necesito una función para escuchar ese cambio y actualizar el campo de entrada. Así que debajo de '''defaults''' he añadido la función '''init()' y estoy escuchando el evento de cambio y ejecutando ''handleDateInputsOptions''.

Fragmento de códigoTEXT
Problema nº 1: Al ejecutar la inicialización de 'daterangepicker''' en ''default: script:'''' aparece la ventana emergente de selección '''daterangepicker' en el lugar correcto, debajo del campo de entrada. Sin embargo, al inicializar '''daterangepicker''' dentro de ''handleDateInputsOptions''', añade '''daterangepicker''' al cuerpo exterior y no debajo de la entrada dentro de nuestro iframe grapesjs.
Al mirar https://www.daterangepicker.com/#options verás que podemos añadir un '''parentEl''', pero al ponerlo en '''iframe''' se añade '''daterangepicker' dentro del iframe, pero no puedo colocarlo dentro del cuerpo del iframe. Tengo la sensación de que la razón por la que añade el '''daterangepicker'' al cuerpo principal y no al iframe es porque inicializo '''daterangepicker''' fuera del modelo. Tengo la sensación de que mi función ''init()''' debería ocurrir dentro de '''default: script:'''? Si es así, ¿cómo lo hago?

Problema nº 2: Para inicializar correctamente ''daterangepicker' en la entrada al cargar, puedo usar '''default: script:'''', pero como escribí en mi script abajo, si quiero inicializar el daterangepicker allí, tendré que escribir la mayor parte de la función 'handleDateInputsOptions''' dos veces para comprobar qué tipo de campo de fecha es la entrada. Esto parece un desperdicio.

¡Cualquier ayuda será muy apreciada!

function gatherDateOptions() {
		var customDateFieldInputs = c.customDateFields.split(',');
		var customDateRangeInputs = c.customDateRangeFields.split(',');
		var customDatetimeInputs = c.customDatetimeFields.split(',');
		var customDatetimeRangeInputs = c.customDatetimeRangeFields.split(',');

const dateInputsOptions = []

Añadir campos de fecha
		si (c.customDateFields.length){
			$.each(customDateFieldInputs, function( index, field ) {
				dateInputsOptions.push({
					valor: campo + " - Fecha", nombre: campo + " - Fecha"
				})
			});
		}
		Añadir campos de dataRange
		if (c.customDateRangeFields.length){
			$.each(customDateRangeInputs, function( index, field ) {
				dateInputsOptions.push({
					valor: campo + " - Rango de fechas", nombre: campo + " - Rango de fechas"
				})
			});
		}
		Añadir campos de fecha y hora
		if (c.customDatetimeFields.length){
			$.each(customDatetimeInputs, function( index, field ) {
				dateInputsOptions.push({
					valor: campo + " - Fechahora", nombre: campo + " - Fecha-hora"
				})
			});
		}
		Añadir campos datetimeRange
		if (c.customDateTimeRangeFields.length){
			$.each(customDatetimeRangeInputs, function( index, field ) {
				dateInputsOptions.push({
					valor: campo + " - Rango de Fechas", nombre: campo + " - Intervalo de Fechas"
				})
			});
		}

fecha de retornoEntradasOpciones;
	}

let dateInputsOptions = gatherDateOptions();

domc.addType('date', {
		model: defaultModel.extend({
			Predeterminados: {
				... defaultModel.prototype.defaults,
				'nombre personalizado': c.labelNombreFecha,
				etiquetaNombre: 'entrada',
				Tipo: "fecha",
				arrastrable: 'forma, forma *', // Solo puede caerse dentro de los elementos de 'forma'
				Droppable: falso, // No se pueden colocar otros elementos dentro
				copiable: false, // No permitir duplicar el componente
				Rasgos: [
					'marcador de posición',
					{
						tipo: 'select',
						etiqueta: 'Seleccionar campo de fecha',
						nombre: 'fechaInputsSelect',
						cambioProp: 1,
						opciones: fechaEntradasOpciones
					},
					{ tipo: 'casilla de verificación', nombre: 'requerido' },
				],
				script: función () {
					var input = this;
					console.log(«Entrada de trabajo», entrada);
					var initDateRange = function() {
						Si quiero inicializar el selector de datarangerangepicker aquí, tendré que escribir la mayor parte de la función handleDateInputsOptions dos veces para comprobar qué tipo de campo de fecha es la entrada. Esto parece un desperdicio.
						$(input).daterangepicker({
						singleDatePicker: cierto,
						showDropdowns: cierto,
						// });
					}

if (typeof daterangepicker == 'undefined' || typeof jQuery == 'undefined' || typeof moment == 'undefined') {

if (typeof jQuery == 'undefined'){
							var jquery = document.createElement('script');
							jquery.src = '//cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js';
							document.body.appendChild(jquery);

jquery.onload = function(){
								loadMoment();
							}
						} else {
							loadMoment();
						}
						function loadMoment(){
							si (tipode de momento == 'indefinido'){
								var moment = document.createElement('script');
								moment.src = '//cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js';
								document.body.appendChild(momento);

moment.onload = function(){
									loadDatePicker();
								}
							} else {
								loadDatePicker();
							}
						}
						function loadDatePicker(){
							if (typeof $ == 'indefinido'){window.$ = jQuery};
							var link = document.createElement('link');
							link.rel = "hoja de estilo";
							link.href = "//cdnjs.cloudflare.com/ajax/libs/bootstrap-daterangepicker/3.0.5/daterangepicker.min.css";
							document.body.appendChild(enlace);

var daterangepicker = document.createElement('script');
							daterangepicker.src = '//cdnjs.cloudflare.com/ajax/libs/bootstrap-daterangepicker/3.0.5/daterangepicker.min.js';
							document.body.appendChild(daterangepicker);

dataranquepicker.onload = initIntervaloFecha;
						}
					} else {
						console.log("todos los liberales presentes");
						initDateRange();
					}
				},
			},
			init() {
				this.handleFechaOpcionesEntradas(); <<<< Esto fracasará porque no sabe cuál es la vista en esta etapa. ¿Quizá se supone que aún debe cargar algo?, lo que me lleva a la siguiente línea:
				this.listenTo(this, 'this.view.el está cargado?????', this.handleDateInputsOptions); <<<< ¿Cuál es ese evento para escuchar en cuanto se carga this.view.el?
				this.listenTo(this, 'change:dateInputsSelect', this.handleDateInputsOptions);
			},
			handleDateInputsOptions() {
				si (typeof $(this.view.el).data('daterangepicker') != 'indefinido'){
					$(this.view.el).data('daterangepicker').remove();
				}
				function initDateRange(input, options) {
					$(entrada).datarangepicker(opciones);
				}
				let dateOption = this.get('dateInputsSelect');
				var val = dateOption.split(' - ');
				var fieldName = "Custom." + val[0];
				var type = val[1].trim().toLowerCase();
				var fieldOptions = {};
				this.set('attributes', {
					nombre: fieldNombre,
					id: val[0],
					Tipo: "texto",
				});

if (escribe == "fecha"){
					fieldOptions = {
						singleDatePicker: cierto,
						showDropdowns: cierto,
					}
				} si no (escribe == "datetime"){
					fieldOptions = {
						singleDatePicker: cierto,
						showDropdowns: cierto,
						TimePicker: cierto,
						localidad: {
							formato: 'MM/DD/YYYY hh:mm A'
						}
					}
				} si no (escribe == "datetimerange"){
					fieldOptions = {
						TimePicker: cierto,
						localidad: {
							formato: 'MM/DD/YYYY hh:mm A'
						}
					}
				}

initDateRange(this.view.el, fieldOptions);
			},
	
}, {
			isComponent(el) {
				var dateType;
				if (tipode el.dataset != "indefinido" && el.dataset.type == "fecha") {
					Typetipo de fecha = verdadero;
				} else {
					DateType = false;
				}
				if(el.tagName == 'INPUT' && dateType){
					return {type: 'date'};
				}
			},
		}),
		view: defaultView
	});

Respuestas (1)

artf10 de diciembre de 2019

La mayor parte de la lógica que haces en 'handleDateInputsOptions' debería estar dentro de tu 'script' de componentes. Tu prop 'dateInputsSelect' contiene el tipo de entrada, así que usa la interpolación en tu 'script' y luego aplica la lógica de 'handleDateInputsOptions'. Otro truco que necesitarías es activar la actualización de 'script' en el lienzo, así que hazlo en tu 'model.init' '''js init() { this.on('change:dateInputsSelect', () => this.trigger('change:script')); }


PD. Hazte un favor a ti mismo... usar la nueva [API de componentes](https://grapesjs.com/docs/modules/Components.html#define-custom-component-type) para definir tipos personalizados, con la antigua es bastante fácil romper cosas

Preguntas y respuestas relacionadas

Continúa investigando con debates sobre temas similares.

Plugins de pago que cumplen con este problema

Seleccionado por temas clave y relevancia de etiquetas para ayudarte a enviar más rápido.

Ver todos los plugins

Cargando recomendaciones de plugins de pago...

Opción gratuita

Consulta los plugins de código abierto de GrapesJS en GitHub O haz una búsqueda rápida en nuestro catálogo gratuito.

Explora plugins gratuitos →
Opción premium

Los plugins premium incluyen soporte, actualizaciones regulares y funciones listas para producción — ahorrando días de trabajo de integración.

Explora plugins premium →

Explorar categorías de plugins

Ve directamente a las páginas de categorías de plugins en el marketplace.