I would like to include a javascript function for preventing user from submiting form twice, but I just cannot call the function on submit click. Here is what I have tried:
<?php echo $this->Form->end(__('Save'), array('onclick'=>'submit();'));?>
I went through the documentation and it seems that the Form->end does not take such parameters, which is really odd. Can that be true?
Any information or help is much appreciated
you need to do in this way : -
$options = array(
'label' => 'submit',
'div' => FALSE,
'onclick'=>'submit()'
);
echo $this->Form->end($options);
This will generate :-
<input type="submit" value="submit" onclick="submit()">
Documentation : Click Here
An alternative solution is to use onSubmit in $this->Form->create()
$this->Form->create('Model', array(
'onsubmit' => 'return submit();',
//other create options
)
And in your JavaScript use a flag to keep track if the form was submitted, and return false if it has. If it hasn't return true and the form will submit.
You might also want to disable the submit button the first time the form is submitted to make it clear to the user that the form can't be submitted again.
Related
I have a situation where I need to prevent Formik from marking as .touched my fields when I Submit. .touched should be set when I touch a field, but clicking Submit should reset .touched to {}. I read in the docs that
Before submitting a form, Formik touches all fields so that all errors
that may have been hidden will now be visible.
I have my own custom isInvalid= definition and my own submitClicked variable that I track myself, so I need to turn off or reverse this behavior. I want errors populated, but I want touched to be empty (reset) after clicking Submit.
I was thinking of calling setTouched({}) somewhere, but I need an event that tells me validation has completed. I also don't know where to insert it; I can't call it from a custom useEffect that watches submitClicked.
<Button type="submit"
onClick{() => {
// my own var.
setSubmitClicked(true);
// If I call setTouched({}) here, it does nothing. It gets overridden after Form Submit
setTouched({});
}} Submit
</Button>
also, can't really do it in a useEffect, I don't have access to Formik here and it's a mess to implement,
useEffect(() => {
someFormikContext.setFieldTouched({}); // hard to get Formik Context here
}, [submitClicked]);
Are there any simpler solutions?
You can reset form on submit ,
onSubmit={(values, { resetForm }) => {
// do your stuff
resetForm();
}}
This will reset your form errors / touched , hope this will help you
I'm building an application that allows for posting community concerns with the ability to upvote those concerns using React, and right now, I am working on the upvote functionality. One way I'm trying to limit the currently logged in user to a single vote is to disable the button once an upvote has been successfully registered for any given post.
To do this, I created a function that checks if the logged in user's ID matches the ID of the upvote for each post. If no match is found, this means the user hasn't voted for already and can register the new upvote. Once this is complete, the button is disabled. I created state for this and is set to false upon the initial render (not sure if this is what I should be doing). I also created state for the all of the votes that have been successfully registered. Both are included below.
const [alreadyVoted, setAlreadyVoted] = useState(false);
const [userVotes, setUserVotes] = useState(upvotes) // upvotes is being passed via props
I'm using the useEffect hook (again, not sure if this is the best way) to check if each button should be enabled or disabled like so:
useEffect(() => {
hasVoted()
}, [userVotes])
Finally, my hasVoted function checks to see if the user has already voted for the issue before and determines the state. It looks like:
function hasVoted() {
userVotes.forEach(vote => {
if (vote.issue_id === issue.id) { // issue here is from props
setAlreadyVoted(true) // I want this to then disable my button
}
})
}
Right now, when I click the button to register the upvote, the page doesn't rerender upon clicking. However, if I refresh the page, the button is successfully disabled as it should be. It probably goes without saying, I'm still getting the hang of React, but any and all help is appreciated.
This code is meaningless at first place
userVotes.forEach(vote => {
if (vote.issue_id === issue.id) { // issue here is from props
setAlreadyVoted(true) // I want this to then disable my button
}
})
, it can be transformed into
if (userVotes.some(vote => vote.issue_id === issue.id)) setAlreadyVoted(true)
but still the logic of it is not clear
I think hasVoted function should be in the useEffect scope. If it's outside, it might introduce bugs, as documented here: https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies
You could try if this helps to resolve your problem
you seem to be somewhat on the right track here but your problem may lay elsewhere,provided the props are passed correctly,because the application does re-render when the state changes. if you want to just disable button you can just use simple html attribute to do that
{alreadyVoted ? (
<button class="btn btn-success" disabled="disabled">
Upvote
</button>
) : (
<button
class="btn btn-success"
onClick={() =>
// Add the id to the setUserVotes here
setAlreadyVoted(true)}
>
Upvote
</button>
)}
Take a look at this codesandbox that i just created and get back to me if you have any issues still
I have a form that can handle submission a couple of different ways. The difference is managed by a flag in the form Values that can either be true or false.
I am running into this really weird issue where when I use the Formik setValues() function the form doesn't enter the handleSubmit function at all. It just stops execution. However if I set the value using just by going this.props.values.x = ...
it enters the function and continues with submitting the form just fine.
Why is this happening?
there's really no point in showing code as the description tells you everything but this is what the submit handler looks like:
A confirmation function calls the submit handler which sets the value and then attempts to call handleSubmit
<Confirmation
items={this.confirmationData()}
isLoading={this.props.isSubmitting}
open={isConfirming}
preapproval={true}
submitAnother={this.submitAnother}
onClick={this.submit} //this is the submit handler
onClose={() => this.setState({ isConfirming: false })}
/>
submit = () => {
this.props.setValues({ ...this.props.values, submit: true})
this.props.handleSubmit()
}
if the first line is changed to this.props.values.submit = true, the form submits however, using the setValues function, The application stops executing after setting the submit value to be true.
Turns out the issue was the is Validating Flag being set to true when you call setFieldValue so the simplest solution is to pass a third argument to setFieldValue to manually turn off validation:
submit = () => {
this.props.setFieldValue('submit', true, false)
this.props.handleSubmit()
}
New to cakephp here.. wondering how i could have a button whilst in my index view to open an add form ( for the same model ). once i submit this form i'd like the modal to disappear and the new record to be show in the index view. I was thinking of putting the add form in a cake element? but not sure how to put this in a modal window. any advice would be great thanks.
What #savedario says makes perfect sense. I blogged about this just before Christmas and have copied the relevant bits below:
View/Users/index.php:
<!-- overlayed element -->
<div id="dialogModal">
<!-- the external content is loaded inside this tag -->
<div class="contentWrap"></div>
</div>
...
<div class="actions">
<ul>
<li>
<?php echo $this->Html->link(__('Add user', true), array("controller"=>"users", "action"=>"add"), array("class"=>"overlay", "title"=>"Add User"));
</li>
</ul>
</div>
...
<script>
$(document).ready(function() {
//prepare the dialog
$( "#dialogModal" ).dialog({
autoOpen: false,
show: {
effect: "blind",
duration: 500
},
hide: {
effect: "blind",
duration: 500
},
modal: true
});
//respond to click event on anything with 'overlay' class
$(".overlay").click(function(event){
event.preventDefault();
$('#contentWrap').load($(this).attr("href")); //load content from href of link
$('#dialogModal').dialog('option', 'title', $(this).attr("title")); //make dialog title that of link
$('#dialogModal').dialog('open'); //open the dialog
});
});
</script>
Views/Users/add.ctp:
echo $this->Form->create('User');
echo $this->Form->input('name');
echo $this->Js->submit('Save', array( //create 'ajax' save button
'update' => '#contentWrap' //id of DOM element to update with selector
));
if (false != $saved){ //will only be true if saved OK in controller from ajax save above
echo "<script>
$('#dialogModal').dialog('close'); //close containing dialog
location.reload(); //if you want to reload parent page to show updated user
</script>";
}
echo $this->Form->end();
echo $this->Js->writeBuffer(); //assuming this view is rendered without the default layout, make sure you write out the JS buffer at the bottom of the page
Controllers/UsersController.php:
function add() {
...
$this->set('saved', false); //false by default - controls closure of overlay in which this is opened
if (!empty($this->request->data)) {
$this->User->create();
if ($this->User->save($this->request->data)){
$this->set('saved', true); //only set true if data saves OK
}
}
...
}
You'll need to have included JQuery 1.9+ and JQuery UI js files in the layout used by your index.ctp and add.ctp.
Actually I have now switched to Bootstrap modals in my own code because I think they look nicer but the approach is very similar.
CakePHP does not have a built-in functionality to do what you want.
Using Elements here does not necessarily help, unless you find yourself writing the same code in different places...
I could not find anything already written to handle this, so I wrote my own javascript functions that work but I doubt could be used as a plugin.
To explain the whole thing would be a bit too long here.
I suggest you start looking at Jquery UI Dialog.
Your index view will need an 'onclick' on the 'add' action button to open the dialog.
The content of the dialog itself could come from the same add() action you would normally use, loaded via an ajax call.
I used bootstrap 3 for my cakephp project which included modals, but that may be overkill for your project.
You have to use bootstrap or jquery to do this. CakePHP does not have a built-in functionality to do what you want.
Typo
<div class="contentWrap"></div>
must be
<div id="contentWrap"></div>
or
$('#contentWrap').load($(this).attr("href"));
must be
$('.contentWrap').load($(this).attr("href"));
I have a question concerning angularJS.
I want to validate a form. If there is an error, I want do an action in order to process the data further. I.e. users has not filled all fields, but I want send the inputs nevertheless.
Thanks in advance...
You should check the $valid attribute of the form inside your controller.
<form name="newFeed">
URL: <input size="80" name="url" ng-model="newFeed.url" type="url" required>
<button ng-click="addFeed(newFeed)">Add Feed</button>
</form>
In a controller, a bound value can be interrogated for the validation status by checking the > $valid property.
$scope.addFeed = function(feed) {
if (feed.$valid) {
// Copy this feed instance and reset the URL in the form
$scope.feeds.push(feed);
$scope.newFeed.url = {};
}
};
(as taken from here).
You check the $valid attribute every time you call addFeed by pressing the submit button.