Update Categories - forms

I am pretty close to a solution but am stuck. I have a category page where the category is created and deleted on the same page. I am adding a edit function, edit link, and making it to where the user can edit the category on the same page instead of creating another static page and repeating the same code.
Here is my controller function for update
public function postEdit() {
$category = Category::find(Input::get('id'));
if ($category) {
$category->update();
return Redirect::to('admin/categories/index')
->with('message', 'Category Updated');
}
return Redirect::to('admin/categories/index')
->with('message', 'Something went wrong, please try again');
}
Here is the category page where a user can view, create, edit, and delete the categories listed I am trying to have a conditional that states to show create form as default and only show edit form when edit button is clicked.
#extends('layouts.main')
#section('content')
<div id="admin">
<h1>Categories Admin Panel</h1><hr>
<p>Here you can view, delete, create, and edit new categories.</p>
<h2>Categories</h2><hr>
<ul>
#foreach($categories as $category)
<li>
{{ $category->name }} -
{{ Form::open(array('url'=>'admin/categories/destroy', 'class'=>'form-inline')) }}
{{ Form::hidden('id', $category->id) }}
{{ Form::submit('delete') }}
{{ Form::close() }}
{{ Form::open(array('url'=>'admin/categories/edit', 'class'=>'form-inline'))}}
{{ Form::hidden('id', $category->id) }}
{{ Form::submit('edit') }}
{{ Form::close() }}
</li>
#endforeach
</ul>
<h2>Create New Category</h2><hr>
#if($errors->has())
<div id="form-errors">
<p>The following errors have occurred:</p>
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div><!-- end form-errors -->
#endif
<php
if(isset(url=>'admin/categories/destroy')) {
{{ Form::open(array('url'=>'admin/categories/create')) }}
<p>
{{ Form::label('name') }}
{{ Form::text('name') }}
</p>
{{ Form::submit('Create Category', array('class'=>'secondary-cart-btn')) }}
{{ Form::close() }}
}else{
{{ Form::open(array('url'=>'admin/categories/edit')) }}
<p>
{{ Form::label('name') }}
{{ Form::text('name') }}
</p>
{{ Form::submit('Create Category', array('class'=>'secondary-cart-btn')) }}
{{ Form::close() }}
}
?>
</div><!-- end admin -->
#stop
Please give me an example of how I can accomplish this on the same view page. I know I somehow have to pass in a variable as the value in the form to fill the category selected.
Thank you for the help.
By the way, if you are a moderator and close my question, I will block my IP address, throw a million IP addresses in the network, and just sign up again and again and again with a temp email.
I tried doing a javascript onclick event and here is my results. I cannot get it to work.
Button for link
{{ HTML::Link('#', 'edit', array('class'=>'form-inline', 'id'=>'button', 'onclick'=>'showEditForm(this)'))}}
Javascript
<script>
function showEditForm(id) {
id.innerHTML="
{{ Form::open(array('url'=>'admin/categories/edit')) }}
<p>
{{ Form::hidden('id', $category->id) }}
{{ Form::label('name') }}
{{ Form::text('name') }}
</p>
{{ Form::submit('Edit Category', array('class'=>'secondary-cart-btn')) }}
{{ Form::close() }}
";
}
</script>

actually your question is perfectly fine, i gave it a -1 due to the rant. none the less, this question really deserves an answer.
let's sum up your problem. you have 3 main tasks.
create
edit
delete
For Create:
pretty easy. use a 2 column layout. on the side bar, show the form to create category. then use ajax to submit. e.g.
$(function(){
$(document).on('submit','#writeCategory', function(e){
var f = $(this);
e.preventDefault();
var d = f.serialize();
$.ajax({
type : POST,
url : //your url,
data : d
}).done(function(data){
alert('submitted');
//you can also prepend/append the submitted data after successful submission
}).fail(function(x,h,r){
alert('error occured')
});
});
});
For Edit:
for editing, you can use Xeditable. the page has all demo, docs in the site.
For delete:
i'l mention a very simplified approach. using data- attribute. if you want to delete a category, probably you will need only the id.
suppose you are looping to show all the categories. while doing so, store the id in a say, data-id attribute. and write a delete link for each category.
e.g. a delete link for single category entity may look like following:
<a href="#" class="delete" data-id={{$i->id}}>delete</a>
rest is easy. just use ajax and delete the link. e.g.
$(function(){
$('.delete').click(function(e){
e.preventDefault();
var a = $(this);
var answer = confirm('Are you sure you want to delete this?');
if (answer)
{
 
$.ajax({
type : 'post',
url : //your url,
data : {id:a.attr('data-id')}
}).done(function(data){
alert('deleted');
}).fail(function(x,h,r){
alert('error occured');
});
}
});
});
you can also modify it. e.g. after deletion, if you are showing the categories in a tabular manner, you can slide up the row (which contains the specified catgory information) hinting that, that category has been deleted.
Addition
For View:
there are loads of javascript model window plugins. just select one and through ajax, show the details.
All 4 tasks, done in one place.
N.B. here i have used jQuery just for convenience. if you want plain javascript, you can write it that way too....

Related

Properly set Symfony's form error rendering position

I try to make a registration form in Symfony 3.4 but it makes me mad that I cannot place errors properly.
This is how I render the form itself:
{{ form_start(registrationForm) }}
{{ form_widget(registrationForm) }}
{{ form_end(registrationForm) }}
And the fields are rendered from a custom template, where I declare that errors should appear under the field:
{% block form_row %}
<div class="form-group">
{{ block('form_label') }}
{{ block('form_widget_simple') }}
{{ block('form_error') }}
</div>
{% endblock %}
However all my errors are appearing above the whole form as li elements in an ul element. I tried to add 'error_bubbling' => false but it won't make any difference. (The error messages come form the Assert annotations on the underlying model object.)
What am I doing wrong?

Symfony2 - Collection type is displayed twice in my view

I have a form with a collection and I can see it properly when I use the following syntax:
form_row(form.items)
Then when I try to render it by myself, it is duplicated.
Here is my code in my twig file:
{{ form_errors(form) }}
{{ form_start(form) }}
... some fields here ...
<div id="{{ form.items.vars.id }}" class="collection items" data-prototype="{{ form_widget(form.items.vars.prototype)|e }}">
<h3>{{ form_label(form.items) }}</h3>
Add
{% for item in form.items %}
{{ form_row(item) }}
{% endfor %}
</div>
... some other fields here ...
{{ form_end(form) }}
Here is my code in my form object:
$builder->add('items', 'collection', array(
'type' => new ItemType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'required' => true,
));
Add here is my output:
<!-- This is the one I need, I removed the prototype for the sake of clarity -->
<div id="bundle_data_items" class="collection items" data-prototype="...">
<h3>
<label class="required">Items</label>
</h3>
Add
</div>
<!-- This one is automatically added. The prototype is empty -->
<div>
<label class="required">Items</label>
<div id="bundle_data_items" data-prototype=""></div>
</div>
Do you have any ideas why this happens?
I followed that documentation. Did I miss something?
Edit:
This happens only when my collection is empty
I found the solution to that.
It turns out that when the collection is empty, the rendering of it never occurs. I could use sjagr solution but as there is some fields I want to render automatically, I cannot use it.
So my solution is the following:
{{ form_errors(form) }}
{{ form_start(form) }}
... some fields here ...
<div id="{{ form.items.vars.id }}" class="collection items" data-prototype="{{ form_widget(form.items.vars.prototype)|e }}">
<h3>{{ form_label(form.items) }}</h3>
Add
{% for item in form.items %}
{{ form_row(item) }}
{% else %}
{% do form.items.setRendered %}
{% endfor %}
</div>
... some other fields here ...
{{ form_end(form) }}
When your collection is empty, the for loop in {% for item in form.items %} never gets to execute, hence form_row(item) never happens. This means, to Twig/Symfony, you never actually outputted the field.
Then you do form_end at the end of the form. This is not usually a big deal, but from the docs:
This helper also outputs form_rest() unless you set render_rest to false
So, you must simply pass a false value for render_rest:
{{ form_end(form, {'render_rest': false}) }}
I'm not sure how form_widget did fix your problem, but I'm also not sure how you tried that alternative - perhaps you ran it outside of the for loop.
As an aside, you should consider making your own form.html.twig template file so you can reuse the markup format you've chosen for your collection. It will allow you to simply do form_widget(...) without having to break apart the pieces and your form_end will always consider the field to be outputted even if the collection is empty.
Unfortunately i cannot comment yet (no 50 rep), but perhaps this is caused the browser itself. A rendering issue due to markup someplace? See if the raw http response has the same thing. Since it works with form_row(form.items) but not your own, it "could be" that.
I would check if it's empty also before outputting it.
Similar thing happened to me, label of CollectionType was rendering twice when Collection is empty, but it was rendering once when there are data.
This is my configuration:
$builder->add('items', CollectionType::class, [
'entry_type' => NumberType::class,
'required' => true,
'label' => 'Fields',
'entry_options' => [
'label' => false,
],
'prototype' => true,
])
and in Twig I was displaying Collection label in this way:
{{ form_label(form.items) }} and rendering field widgets in somewhere else. In this case label was displayed twice, once where this code is placed, and the other at the end of form.
Solution is to change it to:
{{ form_row(form.items) }}
or if you need custom rendering for form widgets like in my case, following code will print only labels:
{% if 0 < (form.items|length) %}
{{ form_label(form.items) }}
{% else %}
{{ form_row(form.items) }}
{% endif %}

Laravel - syntax error, unexpected ';' in blade

I have a problem with blade. I check if user is log in. If is I pass in two input default value from $user ($user->UserName and $user->UserEmail), if not I pass Input::old().
Before I don't check if user is log in it worked fine. Any suggestions??
The view:
#if($errors->has())
<ul>
#foreach ($errors->all() as $error)
<li class="txt-danger">{{ $error }}</li>
#endforeach
</ul>
#endif
#if(Session::has('message'))
<ul>
<li class="txt-success">{{ Session::get('message') }}</li>
</ul>
#endif
{{ Form::open(array('url'=>'contact', 'name'=>'contactform', 'id'=>'contactform')) }}
<p>
#if(Auth::check())
{{ Form::text('name', $user->UserName, array('id'=>'name') }}
#else
{{ Form::text('name', Input::old('name'), array('id'=>'name', 'placeholder'=>'Twoje imię')) }}
#endif
</p>
<p>
#if(Auth::check())
{{ Form::text('email', $user->UserEmail, array('id'=>'email') }}
#else
{{ Form::text('email', Input::old('email'), array('id'=>'email', 'placeholder'=>'Twój e-mail')) }}
#endif
</p>
<p>
{{ Form::text('subject', Input::old('subject'), array('id'=>'subject', 'placeholder'=>'Temat')) }}
</p>
<p>
{{ Form::textarea('message', Input::old('message'), array('id'=>'message', 'placeholder'=>'Wiadomość', 'rows'=>'0')) }}
</p>
{{ Form::submit('Wyślij wiadomość', array('class'=>'mainBtn', 'id'=>'submit')) }}
{{ Form::close() }}
It looks like you're using the Input facade within your form.
The input facade is used to get the values passed by the form once you've submitted it. If you're wanting to use old values being passed back from the controller back to the form you need to pass those as parameters from the controller. Something like:
return View::make('MyView')->with('old', $oldValues);
The reason you're getting the error "syntax error, unexpected ';' in blade" is because you're using the double curly brace {{ }} when you output the Form::text() AND you're using the Input facade within it, so what php is seeing is something like:
echo "<input type='text' name='email'> valuefrominput;</input>";
Basically, Input::old() is writing a semicolon in the middle of your Form::text() code.

same customize form for edit and create page symfony

I have started to use symfony.
I am facing problem for create and edit form customization.
I have created a entity with crud. Now I want to customize 'create form' new.html.twig and I am doing with
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.task) }}
{{ form_row(form.dueDate) }}
{{ form_end(form) }}
My question is for 'edit form': what should I do that I can use the same customized form without duplication?
thanks in advance..
You can set the form action dynamically using a couple of different methods.
First you could pass the action into the template as a variable that is different for each parent template like..
new.html.twig
{{ include('AcmeBundle:Form:_form.html.twig',
{'form': form, 'action': path('create_route') }) }}
edit.html.twig
{{ include('AcmeBundle:Form:_form.html.twig',
{'form': form, 'action': path('edit_route', {'id': form.vars.value.id }) }}
// Or the actual object id if the object has been passed to the template
_form.html.twig
{{ form_start(form, {'action': action }) }}
Or you can check for the presence of an id in your present object and then set the action depending on that. This version does make the template a little less reusable as the action is hardcoded but that would only be an issue if you are planning on having the same form for multiple different pages.
_form.html.twig
{% set action = form.vars.value.id is null
? path('create_route')
: path('edit_route', {'id': form.vars.value.id })
%}
{{ form_start(form, {'action': action }) }}
Note: Strings have been split to multiple lines for readability.

Render collection automatically in Symfony 2 using entity type form

I have a two entities: Products and Categories.
Each entity renders a custom form using the Symfony Form Builder .
I'm trying to include the Categories form inside the Products form using the collection field type. The include line looks like the following:
$builder->add('idCategory', 'collection', array('type' => new CategoryType());
It's working fine (according to the Symfony documentation). But I don't want to create the form with JavaScript, I want to have it rendered with the rest of the form without changing the twig template:
<form action="{{ path('product_create') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<button type="submit">Create</button>
</form>
Is it even possible? Any thoughts?
Do you know the number of categories you want to include in the products?
I found a workaround for this since it seems to be impossible to auto render the form without using JavaScript.
Instead of rendering the whole form at once, using {{ form_widget(form) }}, I'm rendering field by field and using {{ form_widget(form.categoy.vars.prototype) }} to render the Category collection. The template code looks like the following:
<div id="form">
{{ form_start(form) }}
{{ form_errors(form) }}
...
{{ form_row(form.name) }}
{{ form_row(form.price) }}
...
<h2>Categories</h2>
{{ form_row(form.idCategory) }}
{{ form_widget(form.idCategoryNew.vars.prototype) }}
...
<button type="submit">Create</button>
{{ form_end(form) }}
</div>
And the ProductType:
$builder
->add('name'))
->add('price'))
...
->add('idCategory', 'entity', array('class' => 'MyBundle\Entity\Category'))
->add('idCateogryNew', 'collection', array('type' => new CategoryType(), 'allow_add' => true))
...
EDIT:
I found a better workaround which consist in passing the collection form to the twig template. This way is easy to handle the post request after the form submission. If anyone want the code, please ask :)
EDIT 2:
Per #agapitocandemor request:
Inside your MainEntityController (ProductController in my case), search the method that renders the form (newAction in my case) and create the Entity form that you want to render:
public function newAction()
{
$entity = new Product();
$entityform = $this->createForm(new ProductType(), $entity);
$subentityform = $this->createForm(new CategoryType(), new Category);
return $this->render('MyBundle:Product:new.html.twig', array(
'entity' => $entity,
'entityform' => $entityform->createView(),
'subentityform' => $subentityform->createView()
));
}
Finally, in order to render the subentityform you just need to call {{ form_widget(subentityform) }} from the new template of your main entity.