How to disable submit button whenever the form fields are empty? - laravel-8

I have a login form with some input fields such as "email" and "password". This form is created with real-time validation by Laravel and Livewire. Until now, everything is good.
With the livewire rules I want to disable the submit button if the form fields are null or empty with Alpine.js. How do I do that?
app\Http\Livewire\LoginForm
class LoginForm extends Component
{
public $email = '';
public $password = '';
protected $rules = [
'email' => 'required|email',
'password' => 'required|min:12',
];
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function saveUser()
{
$validatedData = $this->validate();
User::create($validatedData);
}
}
LoginForm Component
<form wire:submit.prevent="saveUser">
<input type="email" wire:model="email" class="form-control">
#error('email') <span class="error">{{ $message }}</span> #enderror
<input type="password" wire:model="password" class="form-control">
#error('password') <span class="error">{{ $message }}</span> #enderror
<button type="submit">Login Now</button>
</form>

How about simply checking for the value iteself using blade
<button type="submit" {{ (!is_null($email) && !empty($email) && !is_null($password) && !empty($password)) ? '' : 'disabled' }}>Login Now</button>

In you component you can use a separate property public bool $canBeSubmitted which hold the enabled/disabled state for the button.
class LoginForm extends Component
{
public $email = '';
public $password = '';
/**
* Toggle disabled state of submit button
*/
public bool $canBeSubmitted = false;
protected $rules = [
'email' => 'required|email',
'password' => 'required|min:12',
];
public function updated($email)
{
$this->validateOnly($propertyName);
// Setting $canBeSubmitted to true/false
}
public function saveUser()
{
$validatedData = $this->validate();
User::create($validatedData);
}
}
<form wire:submit.prevent="saveUser">
<!-- inputs -->
<button type="submit" {{ !empty($canBeSubmitted)) ? '' : 'disabled' }}>Login Now</button>
</form>
AlpineJS and Livewire
To have access to the canBeSubmitted property from both, AlpineJS and Livewire, you can make use of the entangled feature.
From the docs:
Livewire has an incredibly powerful feature called "entangle" that allows you to "entangle" a Livewire and Alpine property together. With entanglement, when one value changes, the other will also be changed.

Related

StencilJS trying to set component's internal input tag state according to Prop input

I'm building a custom input tag with stenciljs and I dont understand how to set the inputs disabled or readonly state. I'm passing the property to the component from the parent as an enum with 3 properties as follows:
enum INPUT_STATE {
DISABLED = "disabled",
READONLY = "readonly",
DEFAULT = ""
}
And the component looks as follows:
export class InputFields {
#Prop() inputState: INPUT_STATE;
render() {
return (
<div class="status">
<input type="text" {...INPUT_STATE[this.inputState]}/>
</div>
);
}
}
So basically what I'm trying to do is to set the passed property on the input, be it disabled or readonly and an empty string for default state. How can I achieve this functionality?
INPUT_STATE is an enum. The INPUT_STATE values are strings, so INPUT_STATE[this.inputState] is a string not an object. Strings don't map directly to jsx attributes - you would have to set explicitly:
<input type="text" disabled={this.inputState === INPUT_STATE.DISABLED}/>
By using a watch , you can move the logic out of the JSX:
private inputStateAttr = {};
#Prop() inputState: INPUT_STATE;
#Watch('inputState')
handleInputStateChange(value: INPUT_STATE) {
this.inputStateAttr = {
disabled: INPUT_STATE.DISABLED === value,
readonly: INPUT_STATE.READONLY === value
};
}
render() {
return (
<div class="status">
<input type="text" {...this.inputStateAttr}/>
</div>
);
}

Blazor Server - How to disable a control inside component?

I try to show and disable a button by adding "disabled" class in a component (pre-hidden) but failed - it's not working. Where I did wrong ?
Component Button :
<div class="form-group">
<button class="btn btn-primary #disabled">Disable Me</button>
</div>
#code {
string _password;
string disabled = "";
public void Disable()
{
disabled = "disabled";
}
}
Index.razor :
#page "/"
<h1>How to disable button in component ?</h1>
<button class="btn btn-primary" #onclick="ShowAndDisableButton">Show and disable button</button>
#if (show)
{
<ButtonComponent #ref="button"/>
}
#code
{
ButtonComponent button = new();
bool show = false;
void ShowAndDisableButton()
{
show = true;
button.Disable();
}
}
UPDATED : if I change the ShowAndDisableButton code to
async Task ShowAndDisableButton()
{
show = true;
await Task.Delay(TimeSpan.FromMilliseconds(10)); // add this, wait for a while
button.Disable();
}
and change button code in index.razor to
<button class="btn btn-primary" #onclick="()=>ShowAndDisableButton()">Show and disable button</button>
it works. but I don't know why and don't want to use such way, are there any proper way?
The problem is that button.Disable(); does not cause the normal rerendering.
And it is an overcomoplicated way of doing things.
In the page:
#if (show)
{
<ButtonComponent Disabled="!show" />
}
#code
{
//ButtonComponent button = new();
bool show = false;
void ShowAndDisableButton()
{
show = true;
//button.Disable();
}
}
and the button itself:
<div class="form-group">
<button class="btn btn-primary" disabled="Disabled">Disable Me</button>
</div>
#code {
string _password;
// string disabled = "";
[Parameter] public bool Disabled {get; set; }
}
But you won't be able to use this button.
Use disabled="#disabledState"
Where disabledState is a boolean

Form submit returns a blank page

I'm trying to do a basic login with a form in my .cshtml file that goes like this:
<form method="post">
<input type="text" name="nombre"/>
<input type="password" name="contra"/>
<input type="submit" value="login" />
</form>
And checking it in the .cshtml.cs with his method where I compare each input with a value:
public void OnPost()
{
var Username = Request.Form["nombre"];
var Password = Request.Form["contra"];
if (Username.Equals("jsplata") && Password.Equals("1234"))
{
RedirectToPage("https://www.google.com/");
}
else
{
RedirectToPage("https://www.stackoverflow.com/");
}
}
When I press the submit button it returns a blank page, I don't know what might be wrong about this.
You can try to use below codes :
public IActionResult OnPost()
{
var Username = Request.Form["nombre"];
var Password = Request.Form["contra"];
if (Username.Equals("jsplata") && Password.Equals("1234"))
{
return Redirect("https://www.google.com/");
}
else
{
return Redirect("https://www.stackoverflow.com/");
}
}

Toggle button class using Directive in Angular

I want to toggle a buttons class depending on the state of a form in Angular. The template is based on Bootstrap.
I've setup a directive called IsDirty.
If the form has the class 'ng-valid', add the class 'btn-success' to the submit button.
Alternatively, if the form is dirty and has the class 'ng-dirty', remove the class 'btn-success' from the submit button.
So far this is what I have but it doesn't work.
var angular = require('angular');
angular.module('myApp')
.directive('isDirty', [function() {
return {
restrict: 'E',
link: function(scope, element, attrs, ctrl) {
var submitButton = element.find('.btn-primary');
if(element.hasClass('ng-valid')) {
submitButton.addClass('btn-success');
} else {
submitButton.removeClass('btn-success');
}
scope.$apply();
}
};
}]);
My form:
<form is-dirty class="form-horizontal" role="form" name="profileForm">
<!-- INPUT FIELDS HERE //-->
<button type="submit" class="btn btn-primary">Save Changes</button>
<button type="reset" class="btn btn-default">Cancel</button>
</form>
This should hopefully fix your problem
.directive('ngDirty', [function() {
return {
restrict: 'AE',
link: function(scope, element, attrs, ctrl) {
var submitButton = element[0].querySelector('.btn-primary');
if(element.hasClass('ng-valid')) {
submitButton.classList.add("btn-danger");
} else {
submitButton.classList.remove("btn-danger");
}
}
};
}]);
Plnkr Example
Update:
It's a little dirty but it seems to work and checks each input, you must bind each input to an ng-model though I have used $scope.input
New Plnkr
2nd Update
I have removed the function and brought in a $timeout you will see from the example how it works.
New update with a $timeout as function
Use ngClass for this (btw, I am confused with your class names. In your description you say add/remove the class .btn-success but in the code you are adding/removing .btn-danger. So in the code below, I am sticking with .btn-success):
<form is-dirty class="form-horizontal" role="form" name="profileForm">
<!-- INPUT FIELDS HERE //-->
<button type="submit"
class="btn btn-primary"
ng-class="{'btn-success' : isValid}">
Save Changes
</button>
<button type="reset" class="btn btn-default">Cancel</button>
</form>
And in your directive:
var angular = require('angular');
angular.module('myApp')
.directive('form', [function() {
return {
restrict: 'EA',
link: function(scope, element, attrs, ctrl) {
scope.isValid = element.hasClass('ng-valid');
}
};
}]);
I would further suggest that you actually make the class ng-valid itself with ng-class and use the variable scope.isValid to change between ng-valid and isDirty.

MVC4 View Multiple Submit Buttons - Update label text

At the moment I am working on a MVC4 view with multiple submit buttons. To handle the submit of the different buttons, I use this class:
http://blog.maartenballiauw.be/post/2009/11/26/Supporting-multiple-submit-buttons-on-an-ASPNET-MVC-view.aspx
I have three buttons and one label:
Start
Standby
Resume
How can I display a certain text in that label based on which button is pressed?
I wan to use Ajax.BeginForm to update the label text (so I do not have to reload the webpage).
Thank you in advance!
Update:
For example when I click at the Start Button a method will be executed. This method returns true or false. How to catch this bool and display text in the label, based on the result of the method?
Update 2:
<div>
<fieldset>
<legend>Admin Form</legend>
#Html.Label("Options")
<div id="StartBtn">
<input id="Start" type="submit" value="Start" name="action:Start" />
</div>
<div id="StandbyBtn">
<input id="Standby" type="submit" value="Standby" name="action:Standby" />
</div>
<div id="ResumeBtn">
<input id="Resume" type="submit" value="Resume" name="action:Resume" />
</div>
</fieldset>
</div>
[MultipleButton(Name = "action", Argument = "Start")]
public ActionResult Start()
{
if (start())
{
}
else
{
}
}
From your update I would use an ajax call instead of the ajax form
$('.btnSubmit').on('click', function(){
$.ajax({
url: '#Url.Action('Start', 'Controller')',
type: 'post',
data: {
button: this.id
}
dataType: 'json',
success: function(result){
if(result.Success){
$('.lblText').text(result.SetText);
}
}
});
});
I don't know what you want passed to your controller but if you put the same class on all of your buttons (you need to change them to type button instead of submit also) then this.id will will be the id of the clicked button and that will be sent to the controller
then on your controller have an input field matching what is in the data field
public ActionResult Start(string button){
//do something
//from here http://stackoverflow.com/questions/7732481/returning-json-from-controller-never-a-success
return Json(new { Success = "true", SetText = 'SetText' });
//Where SetText is whatever you want your label set to.
}
You can check on this post. http://www.developersnote.com/2013/02/multiple-button-in-mvc-4.html
#using (Html.BeginForm("ActionTaken", "TestController"))
{
<button name="button" value="ActionOne" class="button" style="width: 200px;">
test1</button>
<button name="button" class="button" style="width: 160px;" value="ActionTwo">
test2</button>
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ActionTaken(string butt)
{
string ButtCommand= butt;
switch (ButtCommand)
{
case "ActionOne":
//do stuff here
case "ActionTwo":
//do stuff here
default:
return View();
}
}