Symfony3 - Repeated FieldType not rendering - symfony-forms

I have a repeated fieldtype that is not being rendered when I access the page.
I have this method in my controller:
/**
* #Route("/{token}", name="pass_reset_form")
*
* Function to reset password.
*/
public function ResetAction(Request $reset, $token)
{
$form = $this->createForm(ResetformType::class);
$form->handleRequest($reset);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('VendorMyBundle:Logins')->findByToken($token);
if (!empty($user))
{
// encode password and update in the DB
$password = $this->get('security.password_encoder')
->encodePassword($user[0], $form["newPassword"]->getData());
$user[0]->setPassword($password);
$em->flush();
$this->addFlash('notice', 'The password has been successfully reset. You can now login.');
return $this->redirectToRoute('login_route');
}
}
return $this->render(
'VendorMyBundle:Default:resetEntry.html.twig',
array('form' => $form->createView())
);
}
and this is the ResetformType:
namespace Vendor\MyBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
class ResetformType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('newPassword', RepeatedType::class, array(
'type' => PasswordType::class,
'invalid_message' => 'The password fields must match.',
'required' => true,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Repeat Password'),
));
}
}
and this is the standard twig code:
{% block body1 %}
{{ form_start(form) }}
<button type="submit">Reset Password</button>
{{ form_end(form) }}
{% endblock %}
Whenever I access the route that takes me on that rendered view I only see the form button. I view page source and all that is in HTML is the form button and a hidden form token field.
<form name="resetform" method="post">
<button type="submit">Reset Password</button>
<input type="hidden" id="resetform__token" name="resetform[_token]" value="2NJ7Uht8bgVUV27GnD4FHrCOjTFCIXXQyraJkG4jSmc" />
</form>
What am I missing?

Answering for anybody who bumps into the same issue.
Either clear your cache or specifically render fields separately, in my case with:
{{ form_row(form.newPassword) }}.

Related

Rendering new list item after adding it from a nested form. React hooks, redux, React Router V6

I am creating a list tracking app with React hooks, Redux, and Ruby on Rails. There is a List model, with a title as a string and completed as a boolean, and a ListItem model with descriptions as a string (the list item), completed boolean, and list_id as an integer.
I am using react route V6 for this and getting a little lost in re-rendering/ updating the page. Here is the breakdown of the application:
On the home screen, you can click to view all Lists and add a new list. when viewing all list each list title is displayed as a link to that list show page. The show page shows the list title, list items and a form to add another list item. Now where I am having trouble is being able to add a new list item, and it display on the page right after submission. Right now when I add a new item, and refresh the page it is not there. But if I click back to view all lists, then click that list again it shows up under the list items.
I tried using useNavigate to navigate to that list show page even though it is already on it but I am getting this error
Uncaught TypeError: Cannot destructure property 'list' of 'location.state' as it is null.
Here is all my components:
App.js
class App extends React.Component {
render(){
return (
<div className="App">
<Navbar/>
<br></br>
<Routes>
<Route path="/" element={<Home/>} />
<Route path="/lists" element={<Lists />} />
<Route path="/lists/new" element={<ListForm />} />
<Route path="/lists/:id" element={<ListContainer />} />
</Routes>
</div>
);
}
}
Lists.js
export default function Lists() {
const lists = useSelector(state => state.lists)
// replaces mapStateToProps
const dispatch = useDispatch()
// replaces mapDispatchToProps
useEffect(() => {
dispatch(fetchLists())
}, [])
return (
<div>
{Array.isArray(lists) && lists.map((list) => {
return (
<Link
key={list.id}
to={`/lists/${list.id}`}
state={{ list: list }}
>
<h2>{list.title}</h2>
</Link>
)
})}
</div>
)
}
ListContainer.js
export default function ListContainer() {
const location = useLocation();
const { list } = location.state;
console.log(list)
return (
<div>
<List list={list}/>
<ListItemForm list={list}/>
</div>
);
}
List.js
export default function List({list}) {
return (
<div>
<h4>{list.title}</h4>
{list.list_items.map((item) => {
return (
<div key={item.id}>
<li key={item.id}>{item.description}</li>
</div>
);
})}
<br></br>
</div>
);
}
and ListItemForm.js
export default function ListItemForm({list}) {
const [item, setItem] = useState("")
const dispatch = useDispatch()
const navigate = useNavigate()
function handleSubmit(e) {
e.preventDefault()
let newItem = {description: item, completed: false, list_id: list.id}
dispatch(createListItem(newItem, list.id))
setItem("")
navigate(`/lists/${list.id}`)
}
return (
<div>
<br></br>
<form onSubmit={handleSubmit}>
<label>Add to your list: </label>
<input value={item} onChange={(e) => setItem(e.target.value)} />
</form>
</div>
)
}
I have been stuck on this for quite some time now and not sure where to go from here or where I am going wrong. Any help is appreciated!!
Sometimes when you navigate to "/lists/:id" you send route state, sometimes you don't. It's undefined when you navigate to "/lists/:id" when adding new list items. This navigation to the route you are already on for editing a list is unnecessary.
Since you are using Redux I don't think there's any need to send a list item in route state at all. Use the id route parameter and your lists redux state to derive the specific list you want to view/edit.
Example
Given: <Route path="/lists/:id" element={<ListContainer />} />
Lists
function Lists() {
const dispatch = useDispatch();
const lists = useSelector((state) => state.lists);
useEffect(() => {
if (!lists.length) {
dispatch(fetchLists());
}
}, [dispatch, lists]);
return (
<div>
{lists.map((list) => (
<Link key={list.id} to={`/lists/${list.id}`}>
<h2>{list.title}</h2>
</Link>
))}
</div>
);
}
ListContainer
import { useParams } from 'react-router-dom';
function ListContainer() {
const { id } = useParams();
const lists = useSelector((state) => state.lists);
const list = lists.find((list) => list.id === id);
return (
<div>
<List list={list} />
<ListItemForm list={list} />
</div>
);
}
ListItemForm
function ListItemForm({ list }) {
const [item, setItem] = useState("");
const dispatch = useDispatch();
function handleSubmit(e) {
e.preventDefault();
dispatch(actions.createListItem(item, list.id));
setItem("");
}
return (
<div>
<br></br>
<form onSubmit={handleSubmit}>
<label>Add to your list: </label>
<input value={item} onChange={(e) => setItem(e.target.value)} />
</form>
</div>
);
}

Issue in react final form

I am using react final form for validation purpose for login page which has forgot password and register link as well, now when I am clicking forgot password or register link ,it should not trigger any validation even though I am not filling my user name and password .I have tried t keep forgot password and register link away from tag but it is still triggering the validation on click of forgot password and register link .It should only trigger the validation when I m hitting submit button.
It should not ask to validate the form when I am clicking on any hyper link on the page as hyperlinks does not have any validations.
Here is the code sample
loginPage = () => {
const {t: translate} = this.props;
const {
match: {
params: {
authUrlKey = ''
} = {},
} = {},
} = this.props;
return (
<Form
onSubmit={ (values)=> this.validateUserCredentials(values)}
render={({ handleSubmit}) => (
<form onSubmit={handleSubmit}>
<button className="hidden" type="submit"/>
<h1 className="hw-block--pb">{translate('login.heading')}</h1>
<p className="hw-text-lead hw-block--pb-small">{translate('login.text')}</p>
{ this.state.description !=='' && <p className="hw-text-lead hw-block--pb-small">{this.state.description}</p> }
<div className="hw-grid">
<div className="hw-grid__item hw-one-whole hw-medium--one-fifth hw-large--one-sixth">
<label className="hw-label">{translate('login.landcode')}
<Field name="landcode" component={Dropdown} options={getCountryList()} onOptionSelect={this.onCountrySelect}/>
</label>
</div>
<div className="hw-grid__item hw-one-whole hw-medium--four-fifths hw-large--five-sixths">
<label className="hw-label">{translate('login.mobileNumber')}
<Field type="text" component={InputType}
validate={composeValidators(mobileNumberRequired, validMobileNumberWithISDCode)}
placeholder={translate('login.mobileNumberPlaceHolder')} name="phoneNumber"/>
</label>
</div>
</div>
<label className="hw-label">{translate('login.password')}
<Field type="password" component={InputType} validate={passwordRequired} placeholder={translate('login.passwordPlaceHolder')} name="password"/>
</label>
<Link className="hw-link" to={{ pathname: '/password/reset', state: {authUrlKey} }}>{translate('login.forgotPassword')}</Link>
<ErrorInfo error={this.state.error} errorMessage={this.state.errorMessage} translate={translate}/>
<div className="hw-block hw-block--mt-small">
<div className="hw-grid">
<div className="hw-grid__item hw-small--one-whole hw-medium--one-quarter hw-block--mb-smaller">
<button className="hw-button hw-button--primary hw-button--full" type="submit">{translate('login.loginButton')}</button>
</div>
<div className="hw-grid__item hw-one-whole hw-medium--three-quarters hw-block--mt-smaller">
<Link className="hw-link"
to={{ pathname: '/register', state: {authUrlKey} }}>{translate('login.registerButton')}</Link>
</div>
</div>
</div>
</form>)}
/>
)}
validations function used in code
export const validMobileNumberWithISDCode = (fieldValue='') => {
const value = trimValue(fieldValue);
const regex1 = /^\+?((45)|(46)|(47))?( )?\d{8,10}$/
return (regex1.test(value))? undefined : message[root.lang].validMobileNumber;
}
export const validMobileNumber = (fieldValue='') => {
const value = trimValue(fieldValue);
const regex1 = /^\d{8,10}$/;
return (regex1.test(value))? undefined : message[root.lang].validMobileNumber;
}
export const mobileNumberRequired = (fieldValue='') => {
const value = trimValue(fieldValue);
return value ? undefined : message[root.lang].mobileNumberRequired;
}
export const passwordRequired = (fieldValue='') => {
const value = trimValue(fieldValue);
return value ? undefined: message[root.lang].passwordRequired;
}
export const required =(fieldValue)=> {
const value = trimValue(fieldValue);
return value ? undefined : message[root.lang].required;
}```
validateUserCredentials -> This function does not contains any validation.It is used to retrieve form values and send it to server
React Final Form calls your validation function on every value change in the form, to ensure that the form validity is always up to date. Since you did not include the code for your validation function, I cannot ascertain what you are attempting to do. Your validation function should be very cheap to run (e.g. required fields, value length, etc.). The actual authentication should happen on submit.

Unable to access mutator functions in Wizard form page while using react-final-form

I am trying to create a Wizard form using react-final-form by referring to this code https://codesandbox.io/s/km2n35kq3v. For my use case I need some mutator functions to be used inside my form fields. This example illustrates how to do that - https://codesandbox.io/s/kx8qv67nk5?from-embed.
I am not sure how to access mutator functions in my form steps when I am using a wizard form instead of a single page form.
I tried to combine both the examples by modifying the <Form> component rendered by Wizard.js to pass in the mutators. However I cannot access these mutators in the Wizard form pages.
In Wizard.js
return (
<Form
mutators={{
// potentially other mutators could be merged here
...arrayMutators,
}}
render={({
handleSubmit,
submitting,
values,
pristine,
invalid,
form: {
mutators: {push, pop, remove},
},
}) => {
return (
<form onSubmit={handleSubmit}>
Another file index.js
<Wizard
initialValues={{ employed: true, stooge: "larry" }}
onSubmit={onSubmit}
>
<Wizard.Page>
<FieldArray name="customers">
{({ fields }) =>
fields.map((name, index) => (
<div key={name}>
<label>Cust. #{index + 1}</label>
<Field
name={`${name}.firstName`}
component="input"
placeholder="First Name"
/>
<span
onClick={() => fields.remove(index)}
style={{ cursor: "pointer" }}
>
❌
</span>
</div>
))
}
</FieldArray>
</Wizard.Page>
</Wizard>
It errors out - remove is undefined in index.js
Look at this working example: https://codesandbox.io/s/znzlqvzvnx
changes I have made:
Wizard.js
static Page = ({ children, mutators }) => {
if(typeof children === 'function'){
return children(mutators);
}
return children;
};
...
<form onSubmit={handleSubmit}>
{
// activePage
<activePage.type {...activePage.props} mutators={mutators} />
}
...
index.js (only first <Wizard.page>)
<Wizard.Page>
{
({ upper }) => (
<React.Fragment>
<div>
<label>First Name</label>
<Field
name="firstName"
component="input"
...
</div>
</React.Fragment>
)
}
</Wizard.Page>

Laravel 4 - username in URL changes to {Username} after pressing submit

I'm new to Laravel and am stuck on a syntax issue. I'm trying to make a view that will enable an admin to change the password of a user but when I click submit the page refreshes and the URL has replaced the username (ex: public/users/alex/edit to public/users/{username}/edit). If anyone could explain why this isn't working it'd be greatly appreciated! I made something similar where the users can change their own password and that one seems to be working fine. My only guess is that I'm not carrying over the $username properly but I haven't a clue of how else to do it. Thank y'all so much! Any bit of info helps!
Here is the UserController for the view:
public function getEdit ($username) {
$user = User::whereUsername($username)->first();
return View::make('users.edit', ['user' => $user]);
}
public function postEdit($username){
$validator = Validator::make(Input::all(),
array(
'password' => 'required|min:6',
'password_again' => 'required|same:password'
)
);
if($validator->fails()){
return Redirect::route('user-edit')
->withErrors($validator)
->with('username', $username);
} else {
/*Change password*/
$user = User::whereUsername($username)->first();
$password = Input::get('password');
$user->password = Hash::make($password);
/*password is the field $password is the variable that will be used in the password field*/
if($user->save()){
return Redirect::route('home')
->with('global', 'The password has been changed.');
}
}
return Redirect::route('account-change-password')
->with('global', 'The password could not be changed.');
}
the Route:
/*ADMIN - edit users (GET)*/
Route::get('users/{username}/edit', array(
'as' => 'user-edit',
'uses' => 'UserController#getEdit'
));
/*ADMIN - edit users (POST)*/
Route::post('users/{username}/edit', array(
'as' => 'user-edit-post',
'uses' => 'UserController#postEdit'
));
and the View/Blade:
#extends('layout.main')
#section('content')
<form action="{{ URL::route('user-edit-post') }}" method="post">
<div class="field">
New password: <input type="password" name="password">
#if($errors->has('password'))
{{$errors->first('password')}}
#endif
</div>
<div class="field">
New password again: <input type="password" name="password_again">
#if($errors->has('password_again'))
{{$errors->first('password_again')}}
#endif
</div>
<input type="submit" value="Change Password">
{{ Form::token() }}
</form>
#stop
It does not seem like you pass the username anywhere inside your form. Have you tried using {{ Form::open(...) }} and {{ Form::close() }} (see http://laravel.com/docs/html)? Those functions will handle parameter passing for you and include hidden variables if necessary.
Good luck!
Michal

jquery ui autocomplete not populating from remote datasource

My first stackoverflow post! So I cannot figure out why this is not working. It was working in the past but it does not now, don't know what changed. The JSON is returning correctly it's just not populating the drop down.
Here is the html:
$(document).ready(function(){
$('#search').autocomplete({
source: 'search.php',
minLength: 2
});
});
</script>
</head>
<body>
<div class="ui-widget">
<label for="search">Search</label>
<input type="text" id="search" />
</div>
</body>
Here is the PHP:
mysql_select_db('symfony',$con);
$autocomplete_value = mysql_real_escape_string($_GET["term"]);
$sql = "SELECT name FROM Artist WHERE name LIKE '%$autocomplete_value%' UNION
SELECT name FROM Event WHERE name LIKE '%$autocomplete_value%'";
$query = mysql_query($sql);
echo $sql;
$results = array();
while ($row = mysql_fetch_array($query, MYSQL_ASSOC)) {
array_push($results, array( 'name' => $row['name']) );
}
json_encode($results);
?>
EDIT**
My coworker helped me figure it out. I need to change
array_push($results, array( 'name' => $row['name']) );
to
array_push($results, array( 'value' => $row['name']) );
Now it works!

Resources