When a modal window is started, there will be no form validation if you use the default way:
$('#someModalWindow')
.modal({
inline: true,
onDeny: function () {
// someting
},
onApprove: function () {
// some action
}
})
.modal('show');
How can a form validation be triggered manually or automatically in the modal window.
I am using meteor below SemanticUI
thanks
I figured out how to do it:
$('#someModalWindow')
.modal({
onDeny: function () {
// someting
},
onApprove: function () {
var validated = $('#myFormId').form('validate form');
if(!validated){
return false;
}
// some action
}
})
.modal('show');
hopefully this can help you.
Related
Example Stencil.js web component:
import { Component, ComponentInterface, Event, EventEmitter, h, Host } from "#stencil/core";
#Component({
tag: 'foo-testwebcomponent'
})
export class TestWebComponent implements ComponentInterface {
#Event({
eventName: 'foo-click',
cancelable: true
}) fooClick: EventEmitter;
fooClickHandler() {
this.fooClick.emit();
}
render() {
return(
<Host>
<a href="#"
onClick={this.fooClickHandler.bind(this)}
>Testing</a>
</Host>
)
}
}
HTML:
<foo-testwebcomponent id="test"></foo-testwebcomponent>
<script>
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('test')
.addEventListener('foo-click', event => {
event.preventDefault();
console.log(`Foo Test Web Component clicked!`);
});
});
</script>
Problem:
In the HTML implementation, the prevent default does not stop the link from working.
Question:
How can I allow the end-user of my web component to prevent default, and stop the link from working?
I know that I can add preventDefault() in the fooClickHandler() (see below), but that seems odd to me. I'd like to give the control to the end user of the web component.
#Event({
eventName: 'foo-click',
cancelable: true
}) fooClick: EventEmitter<MouseEvent>;
fooClickHandler(event: MouseEvent) {
event.preventDefault();
this.fooClick.emit();
}
There are two separate events:
The user-initiated click event
Your fooClick custom event
In your example you call preventDefault() on the custom event but you need to call it on the original click event to prevent the link from navigating.
I know of two ways to achieve this:
1: Track whether your custom event is canceled
You can check whether the user called preventDefault() on your custom event using the defaultPrevented property. The fooClick event handler can stay the same.
fooClickHandler(clickEvent: MouseEvent) {
const customEvent = this.fooClick.emit();
if (customEvent.defaultPrevented) {
clickEvent.preventDefault();
}
}
Check out this online demo.
2: Pass the click event
Pass the click event to the fooClick event handler so the user can cancel it.
fooClickHandler(clickEvent: MouseEvent) {
this.fooClick.emit({ originalEvent: clickEvent });
}
And in the handler:
element.addEventListener('foo-click', event => {
event.detail.originalEvent.preventDefault();
console.log(`Foo Test Web Component clicked!`);
});
One way would be to overload the addEventListener function and capture the function reference
(needs some more work to make it work with nested elements, you get drift)
Or use a custom method addClick(name,func) so the user can still add any listener
<script>
customElements.define(
"my-element",
class extends HTMLElement {
connectedCallback() {
this.clicked = (evt)=>{
document.body.append("component handler")
}
this.onclick = (evt) => {
this.clicked(evt);
}
}
addEventListener(name, func) {
this.clicked = func;
}
}
);
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('my-element')
.addEventListener('click', event => {
document.body.append(`user handler`);
});
});
</script>
<my-element>Hello Web Components World!</my-element>
You could also use good old onevent handlers:
<script>
customElements.define(
"my-element",
class extends HTMLElement {
connectedCallback() {
this.onclick = (evt) => console.log("component handler")
}
}
);
document.addEventListener('DOMContentLoaded', () => {
let el = document.querySelector('my-element');
el.onclick = event => console.log(`user handler`, el.onclick);
});
</script>
<my-element onclick="console.log('inline')">Hello Web Components World!</my-element>
I want to alter how an asyncCommand is being hit (currently from a button), so I would need to access the asyncCommand from code. I don't want to have to alter what this asyncCommand is doing, it is dealing with payment details.
I have tried Googling but I cant find anything, I am also new to KO.
This is what I'm trying to achieve:
Click on a button (a separate button with its own asyncCommand method
which checks a flag) The 'execute' will do the following:
If (flag) - show modal
modal has two options - Continue / Cancel
If continue - hit asyncCommand command for original button (card payment one).
If cancel - go back to form
If (!flag)
Hit asyncCommand command for original button (card payment one).
Can this be done?
Thanks in advance for any help.
Clare
This is what I have tried:
FIRST BUTTON
model.checkAddress = ko.asyncCommand({
execute: function (complete)
{
makePayment.execute();
if (data.shippingOutOfArea === true || (data.shippingOutOfArea === null && data.billingOutOfArea === true)) {
model.OutOfArea.show(true);
}
complete();
},
canExecute: function (isExecuting) {
return !isExecuting;
}
});
ORIGINAL BUTTON
model.makePayment = ko.asyncCommand({
execute: function (complete) {
}})
MODAL
model.OutOfArea = {
header: ko.observable("Out of area"),
template: "modalOutOfArea",
closeLabel: "Close",
primaryLabel: "Continue",
cancelLabel: "Change Address",
show: ko.observable(false), /* Set to true to show initially */
sending: ko.observable(false),
onClose: function ()
{
model.EditEmailModel.show(false);
},
onAction: function () {
makePayment.execute();
},
onCancel: function ()
{
model.EditEmailModel.show(false);
}
};
You will have two async commands actually for this scenario. One to open up the modal and another one for the modal.
Eg:
showPaymentPromptCmd = ko.asyncCommand({
execute: function(complete) {
if (modalRequired) {
showModal();
} else {
makePayement();
}
complete();
},
canExecute: function(isExecuting) {
return !isExecuting;
}
});
//Called by Continue button on your modal.
makePaymentCmd = ko.asyncCommand({
execute: function(complete) {
makePayement();
complete();
},
canExecute: function(isExecuting) {
return !isExecuting;
}
});
var
function makePayement() {
//some logic
}
Session.set('coursesReady', false); on startup.
UPDATE:
I made it into a simpler problem. Consider the following code.
Inside router.js
Router.route('/', function () {
Meteor.subscribe("courses", function() {
console.log("data ready")
Session.set("coursesReady", true);
});
}
and inside main template Main.js
Template.Main.rendered = function() {
if (Session.get('coursesReady')) {
console.log("inject success");
Meteor.typeahead.inject();
}
The message "inject success" is not printed after "data ready" is printed. How come reactivity does not work here?
Reactivity "didn't work" because rendered only executes once (it isn't reactive). You'd need to wrap your session checks inside of a template autorun in order for them to get reevaluated:
Template.Main.rendered = function() {
this.autorun(function() {
if (Session.get('coursesReady')) {
console.log("inject success");
Meteor.typeahead.inject();
}
});
};
Probably a better solution is to wait on the subscription if you want to ensure your data is loaded prior to rendering the template.
Router.route('/', {
// this template will be rendered until the subscriptions are ready
loadingTemplate: 'loading',
waitOn: function () {
// return one handle, a function, or an array
return Meteor.subscribe('courses');
},
action: function () {
this.render('Main');
}
});
And now your rendered can just do this:
Template.Main.rendered = function() {
Meteor.typeahead.inject();
};
Don't forget to add a loading template.
To Solve Your Problem
Template.registerHelper("course_data", function() {
console.log("course_data helper is called");
if (Session.get('coursesReady')) {
var courses = Courses.find().fetch();
var result = [ { **Changed**
name: 'course-info1',
valueKey: 'titleLong',
local: function() {
return Courses.find().fetch();
},
template: 'Course'
}];
Session.set('courseResult', result); **New line**
return Session.get('courseResult'); **New line**
,
Explanation
The answer is at the return of the helper function needs to have be associated with reactivity in order for Blaze, template renderer, to know when to rerender.
Non-reactive (Doesn't change in the DOM as values changes)
Template.Main.helpers({
course_data: UI._globalHelpers.course_data ** Not reactive
});
Essentially: UI._globalHelpers.course_data returns an array of objects which is not reactive:
return [
{
name: 'course-info1',
valueKey: 'titleLong',
local: function() {
return Courses.find().fetch();
},
template: 'Course'
},
Reactive
From Meteor Documentation:
http://docs.meteor.com/#/full/template_helpers
Template.myTemplate.helpers({
foo: function () {
return Session.get("foo"); ** Reactive
}
});
Returning Session.get function to Blaze is reactive; thus, the template will change as the values changes.
I'm working on an example CRUD application with Meteor.js and am not sure how best to empty out the fields of a form. I need it in two places: when the Submit button is clicked, and when the Cancel button is clicked.
I implemented it this way by creating a utility function called clearFormFields() that just uses jQuery to empty their contents, but it doesn't feel as "Meteoric" as it should; I feel it should be scoped better so it doesn't have a global visibility. What am I doing wrong?
function clearFormFields() {
$("#description").val("");
$("#priority").val("");
}
Template.todoNew.events({
'click #cancel': function(event) {
event.preventDefault();
Session.set('editing', false);
clearFormFields();
},
'submit form': function(event) {
event.preventDefault();
var theDocument = {
description: event.target.description.value,
priority: event.target.priority.value
};
if (Session.get("editing")) {
Meteor.call("updateTodo", theDocument, Session.get('theDocumentId'))
}
else {
Meteor.call("insertTodo", theDocument);
}
Session.set('editing', false);
clearFormFields();
/* Could do this twice but hate the code duplication.
description: event.target.description.value = "";
priority: event.target.priority.value = "";
*/
}
});
You could use the native reset method of the DOM form node ?
"submit form":function(event,template){
event.preventDefault();
// ...
template.find("form").reset();
}
http://www.w3schools.com/jsref/met_form_reset.asp
The DOM object that originated the event can be accessed and reset from through event.target.reset();
"submit form":function(event){
event.preventDefault();
//...
event.target.reset();
}
http://docs.meteor.com/#/full/eventmaps
Here's my function:
function confirmFamilyMemDelete()
{
$('#dialog').attr('title', 'Warning').text('Are you sure?').dialog({ buttons:
[{
text: 'Yes',
click: function ()
{
$('#MainContent_cph_btnConfirmDelete').click();
$(this).dialog('close');
alert('Hello');
}
},
{
text: 'No',
click: function ()
{
$(this).dialog('close');
}
}
]
});
return false;
}
I've got a very weird problem. In my aspx page there's a button that gets an id 'MainContent_cph_btnConfirmDelete' after it gets rendered. I want to click it if Yes button is clicked in the jQuery UI dialog. However, I fail to do it. It just skips over that command and alerts 'Hello'. This means the rest of the code inside my Yes button gets executed. And if I take
$('#MainContent_cph_btnConfirmDelete').click();
out and put it just before return false; the button gets clicked. Is this a know issue with jQuery because I can't think of any logical explanation. If so, what is the workaround?
Here is what I think you need:
function confirmFamilyMemDelete()
{
$('#dialog').attr('title', 'Warning').text('Are you sure?').dialog({ buttons:
{
"Yes": function ()
{
$('#MainContent_cph_btnConfirmDelete').trigger('click');
$(this).dialog('close');
alert('Hello');
},
"No": function ()
{
$(this).dialog('close');
}
}
});
return false;
}