How to set up query arguments to `link_to` mojolicious helper? - perl

I want to pass arguments for link generated by link_to helper:
%= link_to 'Change password' => 'auth_remind', { login => $login }
but this does not work.
How to set up query arguments?

It is not documented yet, but in default welcome.html.ep we can found:
%= link_to 'click here' => url_for
So we can do next:
%= link_to 'Change password' => url_for( 'auth_remind' )->query( login => $login )
If we need to set up some arguments for route we may:
%= link_to 'Change password' => url_for( 'auth_remind', { format => 'txt' } )->query( login => $login )

Related

Disable autocomplete in CakePHP form input box

I am creating form inputs with the CakePHP Form helper and some inputs (Most of the time 'username' and 'password') are being autocompleted on create actions, login actions, etc.. this is annoying. I am guessing those are just more common so the browser is using its cookies to try to complete the inputs.
Anyways.. how do I disable this?
In my view:
...
echo $this->Form->input('username', array(
'label' => 'Please enter your username',
'class' => 'pure-u-1-2'
));
echo $this->Form->input('password', array(
'label' => 'Please enter your password',
'class' => 'pure-u-1-2'
));
...
What am I missing?
You can specify attributes to be sent to the form helper. Specify the attribute 'autocomplete' and set its value to 'off'.
...
echo $this->Form->input('username', array(
'label' => 'Please enter your username',
'class' => 'pure-u-1-2',
'autocomplete' => 'off'
));
echo $this->Form->input('password', array(
'label' => 'Please enter your password',
'class' => 'pure-u-1-2',
'autocomplete' => 'off'
));
...
Which results in something like this for your HTML:
<input name="data[Model][username]" autocomplete="off" class="pure-u-1-2" id="ModelUsername" type="text">
You may also do this on the whole form instead of just each input. Just specify the same attribute and value in the form create like so:
...
echo $this->Form->create('Model', array(
'class' => 'class',
'autocomplete' => 'off'
));
This will give you something like this in your HTML:
<form action=".../Model/Action" class="class" autocomplete="off" id="ModelActionForm" method="post" accept-charset="utf-8">
NOTE Several browsers will now ignore autocomplete="off" or autocomplete="false". The workaround is to place a hidden text and password field before all other inputs on your form. The browsers will fill those instead of the ones you want to leave alone.
The best solution is to use autocomplete = new-password
It works great in Chrome and Firefox
Like this:
$this->Form->input('password', array('type' => 'password', 'autocomplete' => 'new-password'));

How do I bind to onclick events for buttons in Mojolicious?

I'm trying to make a small webapp to control the command-line music player I use (mocp), but I'm having trouble hitting routes when the user presses a button on the page. I expect the problem is related to my lack of HTML.
Code:
#!/usr/bin/perl
use Mocp;
use Mojolicious::Lite;
my $mocp = Mocp->new;
for my $action ( qw( play pause stop next previous unpause toggle-pause server ) ) {
get $action => sub {
my $self = shift;
$mocp->$action;
$self->render( 'controls' );
};
}
get '/' => sub { shift->render( 'controls' ) };
app->start;
__DATA__
## controls.html.ep
%= input_tag 'play', type => 'button', value => 'Play'
%= input_tag 'pause', type => 'button', value => 'Pause'
%= input_tag 'volup', type => 'button', value => 'Volume Up'
%= input_tag 'voldown', type => 'button', value => 'Volume Down'
%= input_tag 'toggle', type => 'button', value => 'Toggle'
%= input_tag 'next', type => 'button', value => '>>'
%= input_tag 'previous', type => 'button', value => '<<'
If I navigate to the routes directly (e.g. '/play'), everything works as expected. The goal is to simply click the 'Play' button to execute the associated method, rather than having to type the route out by hand. My questions at this stage are:
Is mapping these methods to routes the best way to go about this?
If so, how do I trigger a route with an 'onclick' button event as in JavaScript?
Any advice is much appreciated.
Using jQuery on client side you can trigger route with $.get() function
%= input_tag 'play', type=>'button', value=>'Play', onclick=>"$.get('/play')"
or
<input type="button" value="Play" onclick="$.get('/play');">
To use jQuery you have to add the following line into your template
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>

Devise: Combine SignIn and ForgotPass forms into one

As shown in the attached image, I want to combine the Sign In form and the Forgot password form into one form. I am using DEVISE and RoR 3.2.5.
The Sign In form looks like:
= simple_form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => {:class => 'form-horizontal'}) do |f|
.inputs
= f.input :login, :required => false, :autofocus => true, :hint => "Enter either email ID or username"
= f.input :password, :required => false
= f.input :remember_me, :as => :boolean if devise_mapping.rememberable?
.form-actions{ :style => "padding-left: 160px;"}
= f.button :submit, "Sign in", :class => "btn btn-primary"
The Forgot password form looks like:
= simple_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f|
= f.error_notification
.inputs
= f.input :login, :required => true, :hint => "Enter either email ID or username"
.form-actions{ :style => "padding-left: 160px;"}
= f.button :submit, "Send me reset password instructions", :class => "btn btn-primary"
One way is to create a new controller method that reads the value of the submit button.
Based on that value, you should be able to route between the 2 distinct actions.
Another -and probably more modern and clean- way would be to attach javascipt onclick events on one of the buttons that will ignore the form action and submit to a different route.
Rough example:
<script>
$('#forgot-submit-button').click(function(){
$('#my-form').attr('action','<%= forgot_password_path %>').submit()
});
</script>
Not enough time to test this, so please treat it as an example.

CakePHP 2.1 Contact Form in Element Won't Send

I have two contact forms in my CakePHP application -- one with its own Controller, Model, and View, and another one in an element that can be accessed as a "quick" contact form from the footer of every page on the site.
The code for both forms is the same. The element is intended to access the Controller and Model that the other form uses. However, the element is not submitting the data or sending the email, while the regular page works just fine.
Here is the MVC Code for the regular form that IS working:
<!-- Model: Model/Contact.php -->
<?php
class Contact extends AppModel {
var $name = 'Contacts';
public $useTable = false; // Not using the database, of course.
var $validate = array(
'name' => array(
'rule' => '/.+/',
'allowEmpty' => false,
'required' => true,
),
'email' => array(
'allowEmpty' => false,
'required' => true,
)
);
function schema() {
return array (
'name' => array('type' => 'string', 'length' => 60, 'class' => 'contact input'),
'email' => array('type' => 'string', 'length' => 60, 'class' => 'contact input'),
'message' => array('type' => 'text', 'length' => 2000, 'class' => 'contact input'),
);
}
}
?>
<!-- Controller: Controller/ContactsController.php -->
class ContactsController extends AppController
{
var $name = 'Contacts';
/* var $uses = 'Contact'; */
var $helpers = array('Html', 'Form', 'Js');
var $components = array('Email', 'Session');
public function index() {
if(isset($this->data['Contact'])) {
$userEmail = $this->data['Contact']['email'];
$userMessage = $this->data['Contact']['message'];
$email = new CakeEmail();
$email->from(array($userEmail));
$email->to('email#example.com');
$email->subject('Website Contact Form Submission');
$email->send($userMessage);
if ($email->send($userMessage)) {
$this->Session->setFlash('Thank you for contacting us');
}
else {
$this->Session->setFlash('Mail Not Sent');
}
}
}
public function contact() {
if(isset($this->data['Contact'])) {
$userEmail = $this->data['Contact']['email'];
$userMessage = $this->data['Contact']['message'];
$email = new CakeEmail();
$email->from(array($userEmail));
$email->to('email#example.com');
$email->subject('Website Contact Form Submission');
$email->send($userMessage);
if ($email->send($userMessage)) {
$this->Session->setFlash('Thank you for contacting us');
// $this->redirect(array('controller' => 'pages', 'action' => 'index'));
}
else {
$this->Session->setFlash('Mail Not Sent');
}
}
}
}
?>
<!-- View: Views/Contacts/index.ctp -->
<?
$main = 'contact';
$title = 'quick contact';
?>
<div style="border-bottom: solid 1px #ccc;">
<h1 style="position:relative; float:left;"><?php echo $main; ?></h1>
<h2 style="position:relative;float:left;margin-top:15px; color: #869c38"> • <?php echo $title;?></h2>
<br><br>
</div>
<div class="clear"><br></div>
<div id="interior-page">
<?php
echo $this->Form->create('Contact');
echo $this->Form->input('name', array('default' => 'name (required)', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->input('email', array('default' => 'email (required)', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->input('message', array('default' => 'message', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->submit();
echo $this->Form->end();
?>
</div>
And here is the view for the quick contact form that is NOT working, located in an element displayed in the footer of the default layout:
<?php
echo $this->Form->create('Contact');
echo $this->Form->input('name', array('default' => 'name (required)', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->input('email', array('default' => 'email (required)', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->input('message', array('default' => 'message', 'onfocus' => 'clearDefault(this)'));
echo $this->Form->submit();
echo $this->Form->end();
?>
I tried different ways of changing the form action, but I couldn't figure that out.
Usually, cake "automagically" creates the action of the form based on where you call it from E.g. if called from the view Views/Contacts/index.ctp, it will set the action to /contacts/index. In case of an element, Cake can't really guess what you're trying to do, so you need to set the action manually:
$this->Form->create('Contact', array('action' => 'index'));
Or set the full URL alternatively:
$this->Form->create('Contact', array('url' => '/contacts/index'));
Make sure you're including the Contact model for use on every page you need to create that form. In your case, since it's in your layout, that likely means you should put it in your AppController, so every page has access to it.
You also need to specify where the form should submit to:
echo $this->Form->create('Contact', array(
'url' => array('controller'=>'contacts', 'action'=>'contact')
)
);
Off-note - You can combine the last 2 lines:
echo $this->Form->end('Submit');
This creates the submit button with text "Submit" and also closes the form.
Thanks for this! It helped me a lot.
Just a quick thing, you're sending the email twice.
Once here:
$email->send($userMessage);
And again here:
if ($email->send($userMessage))
The first instance ($email->send($userMessage)) isn't necessary.
Cheers

Haml Form Not Submitting in Sinatra App

I'm having problems submitting my form now that I've converted from erb to haml in a simple sinatra app.
new.haml
%form{ :action => "/new", :method => "post"}
%fieldset
%ol
%li
%label{:for => "username"} Name:
%input{:type => "text", :username => "name", :class => "text"}
%input{:type => "submit", :value => "Send", :class => "button"}
In my app.rb
get '/new' do
haml :new
end
post '/new' do
radcheck = Radcheck.new(:username => params[:username])
if radcheck.save
redirect '/'
else
"Hello World"
end
end
each time I get the Hello World statement appear. My logs show nothing interesting.
Any ideas? Worked just fine with erb??
This is what I've tested
get '/new' do
haml :new
end
post '/new' do
#radcheck = Radcheck.new(:username => params[:username])
username = params[:username]
if username
username
else
"Hello World"
end
end
and new.haml
%form{ :action => "/new", :method => "post"}
%fieldset
%ol
%li
%label{:for => "username"} Name:
%input{:type => "text", :name => "username", :class => "text"}
%input{:type => "submit", :value => "Send", :class => "button"}
And it works as expected. So for some reason radcheck.save is returning false, but that has nothing to do with haml. (But notice that I have corrected input with :name => "username")