symfony request returns only one request - twig

i am working with symfony 3 and twig. I take DNS info from a API. But i can never know how many rows it will be. So here is the problem lets say domain www.example.com has 3 DNS's when i request get form my controller i only get the last DNS back from the form.
twig:
{% if dnsinfo is defined %}
<form class="form-inline" method="post" action="/setdns">
{% if dnsinfo is not empty %}
{% for dns in dnsinfo %}
<div class="row " >
<div class="input-group col-xs-3">
<input type="text" id="dns" name="dns" value="{{ dns.1 }}" class="form-control">
</div>
<div class="col-xs-2 input-group">
<select class="form-control" id="type" name="type" style="width:100%;">
<option value="notselected" selected disabled>* Select a type</option>
<option value="A"{% if dns.2 == 'A' %} selected{% endif %}>A</option>
<option value="AAAA"{% if dns.2 == 'AAAA' %} selected{% endif %}>AAAA</option>
<option value="CNAME"{% if dns.2 == 'CNAME' %} selected{% endif %}>CNAME</option>
<option value="MX"{% if dns.2 == 'MX' %} selected{% endif %}>MX</option>
<option value="SOA"{% if dns.2 == 'SOA' %} selected{% endif %}>SOA</option>
<option value="TXT"{% if dns.2 == 'TXT' %} selected{% endif %}>TXT</option>
<option value="SRV"{% if dns.2 == 'SRV' %} selected{% endif %}>SRV</option>
</select>
</div>
<div class="col-xs-3">
<input type="text" id="content" name="content" value="{{ dns.3 }}" class="form-control">
</div>
<div class="col-xs-1">
<input type="text" id="ttl" name="ttl" value="{{ dns.4 }}" class="form-control">
</div>
<div class="col-xs-3">
<input type="text" id="prio" name="prio" value="{{ dns.5 }}" class="form-control">
</div>
</div>
<hr class="divider" style="">
{% endfor %}
{% endif %}
<input type="submit" class="btn btn-success" value="Save">
Cancel
</form>
{% endif %}
symfony controller:
$this->pre($request->request->get('dns'));
$API = $this->connect();
$dns = array(
'domain' => $request->request->get('domain'),
'extension' => $request->request->get('ext'),
'dnsdata' => serialize( array(
1 => array(
'name' => $request->request->get('dns'),
'type' => $request->request->get('type'),
'content' => $request->request->get('content'),
'ttl' => $request->request->get('ttl'),
'prio' => $request->request->get('prio')
)
))
);
$API->prepare('dns', $dns);
Of course i know a solution. Working with numbers behind the fields name1 name2 etc. But there must be a better way to do this right? What i am trying to get is if i print my request:
[dns] => array (array with all the DNS's i send in my form)
this is what is inside form data
https://gyazo.com/ebd558ba7f1ef8e1bfbe86e115bbb1e
as you can see it hold all the data i need yet with $request->request->get() i can only take the last one.
So my question is how to get all the data out?
vardump and the form that returns all the fields https://gyazo.com/0b9725ba8e298c6f59f343d3d5a548c7
sollution:
I ended up working with numbers so i can know how many fields are send from the api. And then looping to all of the fields
{% if dnsinfo is defined %}
{% set i=0 %}
<form class="form-inline" method="post" id="form" action="/setdns">
<input value="{{ domain }}" hidden name="domain" id="domain">
<input value="{{ ext }}" hidden name="ext" id="ext">
{% if dnsinfo is not empty %}
{% for dns in dnsinfo %}
<div class="row " >
<div class="input-group col-xs-3">
<input type="text" id="dns{{ i }}" name="dns{{ i }}" value="{{ dns.1 }}" class="form-control">
</div>
<div class="col-xs-2 input-group">
<select class="form-control" id="type{{ i }}" name="type{{ i }}" style="width:100%;">
<option value="notselected" selected disabled>* Select a type</option>
<option value="A"{% if dns.2 == 'A' %} selected{% endif %}>A</option>
<option value="AAAA"{% if dns.2 == 'AAAA' %} selected{% endif %}>AAAA</option>
<option value="CNAME"{% if dns.2 == 'CNAME' %} selected{% endif %}>CNAME</option>
<option value="MX"{% if dns.2 == 'MX' %} selected{% endif %}>MX</option>
<option value="SOA"{% if dns.2 == 'SOA' %} selected{% endif %}>SOA</option>
<option value="TXT"{% if dns.2 == 'TXT' %} selected{% endif %}>TXT</option>
<option value="SRV"{% if dns.2 == 'SRV' %} selected{% endif %}>SRV</option>
</select>
</div>
<div class="col-xs-3">
<input type="text" id="content{{ i }}" name="content{{ i }}" value="{{ dns.3 }}" class="form-control">
</div>
<div class="col-xs-1">
<input type="text" id="ttl{{ i }}" name="ttl{{ i }}" value="{{ dns.4 }}" class="form-control">
</div>
<div class="col-xs-3">
<input type="text" id="prio{{ i }}" name="prio{{ i }}" value="{{ dns.5 }}" class="form-control">
</div>
</div>
<hr class="divider" style="">
{% set i = i + 1 %}
{% endfor %}
{% endif %}
<input type="submit" class="btn btn-success" onclick="$('#form').attr('action','/setdns{{ i }}')" value="Save">
Cancel
</form>
{% endif %}
as you can see in my button i use jquery to send the number to my controller
/**
* #Route("/setdns{i}", name="setdns", requirements={"i": "\d+"})
*/
public function setdns(Request $request, $i = false) {
$API = new Whoisdomainmodify();
$API = $API->connect();
for ($x=0; $x < $i; $x++) {
$dns = array(
'domain' => $request->request->get('domain'),
'extension' => $request->request->get('ext'),
'dnsdata' => serialize(array(
1 => array(
'name' => $request->request->get('dns'.$x),
'type' => $request->request->get('type'.$x),
'content' => $request->request->get('content'.$x),
'ttl' => $request->request->get('ttl'.$x),
'prio' => $request->request->get('prio'.$x)
)
))
);
echo '<pre>';
print_r($dns);
$API->prepare('dns', $dns);
// $API->execute();
// $API->fetch();
}
$this->addFlash('Success', 'DNS successfully changed');
return $this->redirectToRoute('registereddomain');
}
if there is a better way to do this please tell me. Because i send all my form data see gyazo.

Did you know that the for loop in Twig has variables:
http://twig.sensiolabs.org/doc/tags/for.html#the-loop-variable
for example you could use:
{{ dns.loop.index0 }}
or something along those lines. Try it out. Twig is very powerful, if you get familiar with it, it might save you a lot of coding. I'm not sure if this is an answer, but it might help you out.

Related

'Request missing required body param' when submitting front end entry form - Craft CMS

I'm pretty new to craft and creating my first front end entry form using the demo code provided by craft. For some reason I'm getting a 'Request missing required body param' error. I've tried adding <input type="hidden" name="entryId" value=""> but that didn't solve the issue.
Here's my code:
{% extends "_layout.twig" %}
{% macro errorList(errors) %}
{% if errors %}
{{ ul(errors, {class: 'errors'}) }}
{% endif %}
{% endmacro %}
{# If there were any validation errors, an `entry` variable will be
passed to the template, which contains the posted values
and validation errors. If that’s not set, we’ll default
to a new entry. #}
{% set entry = entry ?? create('craft\\elements\\Entry') %}
{# Add `enctype="multipart/form-data"` to `<form>` if you’re
uploading files. #}
<form method="post" accept-charset="UTF-8" enctype="multipart/form-data">
{{ csrfInput() }}
{{ actionInput('entries/save-entry') }}
{{ redirectInput('viewentry/{slug}') }}
{{ hiddenInput('friends', '2') }}
<input type="hidden" name="entryId" value="">
<div class="mb-6">
<label for="title" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your Dog's Name</label>
{{ input('text', 'title', entry.title, {
id: 'title',
class:'bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500',
}) }}
{{ _self.errorList(entry.getErrors('title')) }}
</div>
<div class="mb-6">
<label for="featureImage" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Feature Image</label>
{{ input('file', 'featureImage', entry.featureImage, {
id: 'featureImage',
}) }}
{{ _self.errorList(entry.getErrors('featureImage')) }}
</div>
<div class="mb-6">
<label for="postContent" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Tell us about your dog</label>
{{ tag('textarea', {
id: 'postContent',
name: 'fields[postContent]',
class:'bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500',
}) }}
{{ _self.errorList(entry.getErrors('postContent')) }}
</div>
<div class="mb-8">
<label for="postCategories" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Breed</label>
<select name="fields[postCategories]" id="postCategories">
{# Create a category query with the 'group' parameter #}
{% set myCategoryQuery = craft.categories()
.group('blog') %}
{# Fetch the categories #}
{% set categories = myCategoryQuery.all() %}
{# display post categories #}
{% if entry.postCategories|length %}
<div class="border-t py-2 mb-6">
{% for category in entry.postCategories.all() %}
<a href="{{ category.url }}" class="inline-block border rounded px-2 py-1 text-sm">
{{- category.title -}}
</a>
{% endfor %}
</div>
{% endif %}
{% nav category in categories %}
<li>
<option>{{ category.title }}</option>
</li>
{% endnav %}
</select>
</div>
{#
{% set field = craft.app.fields.getFieldByHandle('postCategories') %}
{{ hiddenInput('fields[postCategories]', '') }}
<select multiple name="fields[postCategories][]">
{% for option in field.options %}
{% set selected = entry is defined
? entry.postCategories.contains(option.value)
: option.default %}
<option value="{{ option.value }}"
{% if selected %} selected{% endif %}
>
{{ option.label }}
</option>
{% endfor %}
</select>
#}
<div class="mb-6">
<button type="submit" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Publish</button>
</div>
</form>
{% endblock %}
I didn't realise that the 2 in {{ hiddenInput('sectionId', '2') }} had to be changed for the ID of the channel - not the handle.
For anyone else stuck with this, the ID can be found in the URL when you're editing the channel in the dashboard settings.
More details here >>

Not sure why im getting a (CSRF token missing or incorrect.) error in django

HTML:
{% extends 'generic.html' %}
{% load static %}
{% block title %}
<title>Projects - Login</title>
{% endblock %}
{% block content %}
<form action='#', method='post'>
{% csrf_token %}
<label for="username">Username</label>
<input type="text" name="username" id="username">
<label for="password">Password</label>
<input type="password" name="password" id="password">
<input type='submit' value='Login!'>
</form>
{% endblock %}
views.py:
def login(request):
return render(request, 'login.html')
urls.py:
urlpatterns = [
path('login/', views.login, name='login')
]
I have tried putting a #csrf_protect decorator on the login function. however I still get the same error.
Change the form in your template:
<form action="{% url 'your_app_name:login' %}" method="post">
{% csrf_token %}
...
</form>
or,
<form action="login/" method="post">
{% csrf_token %}
...
</form>

Django Form issue

I am using Django to select language. One option works fine, but the other won't work
Option (1) Works fine .
<select name="language"
onchange="this.form.submit()" >
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% for lang in LANGUAGES %}
<option value="{{ lang.0 }}" {% if lang.0 == LANGUAGE_CODE %} selected="selected"{% endif %} >{{ lang.1 }} ({{ lang.0 }})</option>
{% endfor %}
</select>
Option 1 : Not working using (form Submit Button )
<form action="{% url 'set_language' %}" method="post" id="LanForm" name="LanForm">
{% csrf_token %}
<input class="lang" id="language" name="language" type="hidden" value="ar">
<input class="lang" id="setl" name="setl" type="submit" value="Go">
</form>
The select option works fine and change the language and redirect properly . But if I use the "Go" button , nothing is changing . I am wondering what is issue.
Firstly you do not set more than one node with the same id.
Secondly, you have kept the name of both submit and hidden inputs same i.e, 'language'.
Use the below snippet and test again
<form action="{% url 'set_language' %}" method="post" id="LanForm" name="language">
{% csrf_token %}
<input class="lang" id="language" name="language" type="hidden" value="ar">
<input class="lang" type="submit" value="Go">
</form>
I managed to fix this issue by modfing the form as follows,
<form action="{% url 'set_language' %}" method="post" id="LanForm" name="LanForm">
{% csrf_token %}
<input name="next" type="hidden" value="{{ request.get_full_path|slice:'3:' }}" />
<input name="language" type="hidden" value="ar" />
<input class="lang" name="language2" type="button" value="Go" onclick=" document.getElementById('LanForm').submit();" >
</form>
No ids no names in the input field

How to Add Extra Tab Using Template Language Twig In OpenCart 3.x

I want an extra description tag termed "Overview" for the product page under the nav nav-tabs class.
This is the complete Twig template code:
<ul class="nav nav-tabs">
<li class="active">{{ tab_description }}</li>
{% if attribute_groups %}
<li>{{ tab_attribute }}</li>
{% endif %}
{% if review_status %}
<li>{{ tab_review }}</li>
{% endif %}
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab-description">{{ description }}</div>
{% if attribute_groups %}
<div class="tab-pane" id="tab-specification">
<table class="table table-bordered">
{% for attribute_group in attribute_groups %}
<thead>
<tr>
<td colspan="2"><strong>{{ attribute_group.name }}</strong></td>
</tr>
</thead>
<tbody>
{% for attribute in attribute_group.attribute %}
<tr>
<td>{{ attribute.name }}</td>
<td>{{ attribute.text }}</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
</div>
{% endif %}
{% if review_status %}
<div class="tab-pane" id="tab-review">
<form class="form-horizontal" id="form-review">
<div id="review"></div>
<h2>{{ text_write }}</h2>
{% if review_guest %}
<div class="form-group required">
<div class="col-sm-12">
<label class="control-label" for="input-name">{{ entry_name }}</label>
<input type="text" name="name" value="{{ customer_name }}" id="input-name" class="form-control" />
</div>
</div>
<div class="form-group required">
<div class="col-sm-12">
<label class="control-label" for="input-review">{{ entry_review }}</label>
<textarea name="text" rows="5" id="input-review" class="form-control"></textarea>
<div class="help-block">{{ text_note }}</div>
</div>
</div>
<div class="form-group required">
<div class="col-sm-12">
<label class="control-label">{{ entry_rating }}</label>
{{ entry_bad }}
<input type="radio" name="rating" value="1" />
<input type="radio" name="rating" value="2" />
<input type="radio" name="rating" value="3" />
<input type="radio" name="rating" value="4" />
<input type="radio" name="rating" value="5" />
{{ entry_good }}</div>
</div>
{{ captcha }}
<div class="buttons clearfix">
<div class="pull-right">
<button type="button" id="button-review" data-loading-text="{{ text_loading }}" class="btn btn-primary">{{ button_continue }}</button>
</div>
</div>
{% else %}
{{ text_login }}
{% endif %}
</form>
</div>
{% endif %}</div>
</div>
With this code, the page looks like this:
I want one more tab there saying OVERVIEW with different content.
Can anyone help me out here with this?
P.S: I did read this: how to add extra tab without any extension in product page in opencart
But, I'm not sure where to find this piece of code (I've tried looking product TPL files as well).
You Should try this its will add new tab name Overview
<ul class="nav nav-tabs">
<li class="active">{{ tab_description }}</li>
{% if attribute_groups %}
<li>{{ tab_attribute }}</li>
{% endif %}
{% if review_status %}
<li>{{ tab_review }}</li>
{% endif %}
<li>Overview</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab-description">{{ description }}</div>
{% if attribute_groups %}
<div class="tab-pane" id="tab-specification">
<table class="table table-bordered">
{% for attribute_group in attribute_groups %}
<thead>
<tr>
<td colspan="2"><strong>{{ attribute_group.name }}</strong></td>
</tr>
</thead>
<tbody>
{% for attribute in attribute_group.attribute %}
<tr>
<td>{{ attribute.name }}</td>
<td>{{ attribute.text }}</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</table>
</div>
{% endif %}
{% if review_status %}
<div class="tab-pane" id="tab-review">
<form class="form-horizontal" id="form-review">
<div id="review"></div>
<h2>{{ text_write }}</h2>
{% if review_guest %}
<div class="form-group required">
<div class="col-sm-12">
<label class="control-label" for="input-name">{{ entry_name }}</label>
<input type="text" name="name" value="{{ customer_name }}" id="input-name" class="form-control" />
</div>
</div>
<div class="form-group required">
<div class="col-sm-12">
<label class="control-label" for="input-review">{{ entry_review }}</label>
<textarea name="text" rows="5" id="input-review" class="form-control"></textarea>
<div class="help-block">{{ text_note }}</div>
</div>
</div>
<div class="form-group required">
<div class="col-sm-12">
<label class="control-label">{{ entry_rating }}</label>
{{ entry_bad }}
<input type="radio" name="rating" value="1" />
<input type="radio" name="rating" value="2" />
<input type="radio" name="rating" value="3" />
<input type="radio" name="rating" value="4" />
<input type="radio" name="rating" value="5" />
{{ entry_good }}</div>
</div>
{{ captcha }}
<div class="buttons clearfix">
<div class="pull-right">
<button type="button" id="button-review" data-loading-text="{{ text_loading }}" class="btn btn-primary">{{ button_continue }}</button>
</div>
</div>
{% else %}
{{ text_login }}
{% endif %}
</form>
</div>
{% endif %}
<div class="tab-pane" id="tab-overview">
<h1>Overview</h1>
<!-- Your HTML and twig code here-->
</div>
</div>
Output Image
You have just add two things
in ul tag add this li
<li>My Tab</li>
and add one div for tab-content
<div class="tab-pane" id="tab-overview">
<h1>My Tab Content</h1>
<!-- Your HTML and twig code here-->
</div>

wrap checkboxes with custom html in Twig template using form entity fieldtype (Symfony3)

I would like to wrap the checkboxes with custom HTML in twig template when Symfony3 renders the form.
Instead of this:
<input type="checkbox" id="form_role_1" name="form[role][]" value="1" />
<label for="form_role_1">ROLE 1</label>
<input type="checkbox" id="form_role_2" name="form[role][]" value="2" />
<label for="form_role_2">ROLE 2</label>
<input type="checkbox" id="form_role_3" name="form[role][]" value="3" />
<label for="form_role_3">ROLE 3</label>
I would like to get something like this:
<div class="input-group">
<input type="checkbox" id="form_role_1" name="form[role][]" value="1" />
<label for="form_role_1">ROLE 1</label>
</div>
<div class="input-group">
<input type="checkbox" id="form_role_2" name="form[role][]" value="2" />
<label for="form_role_2">ROLE 2</label>
</div>
<div class="input-group">
<input type="checkbox" id="form_role_3" name="form[role][]" value="3" />
<label for="form_role_3">ROLE 3</label>
</div>
in the controller action:
$form = $this->createForm(RolesFormType::class, $roles);
$form->handleRequest($request);
return $this->render(
'role/edit_roles.html.twig',
array(
'form' => $form->createView()
)
);
in the form type:
class RolesFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('role', EntityType::class, array(
'label' => 'form.elements.roles',
'class' => 'RoleBundle\Entity\Role',
'choice_label' => 'role_name',
'expanded' => true,
'multiple' => true
));
}
}
the classic template looks like this:
<div class="container-fluid">
<div class="row">
{{ form_start(form, {'method': "POST"}) }}
<div class="col-md-12">
<div class="form-group">
{{ form_errors(form.role) }}
{{ form_widget(form.role, {}) }}
</div>
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
</div>
I tried it this way in the twig template, but only the labels were rendered:
<div class="container-fluid">
<div class="row">
{{ form_start(form, {'method': "POST"}) }}
<div class="col-md-12">
{% for role in form.role %}
<div class="input-group">
{{ form_label(role) }}
{{ form_widget(role) }}
</div>
{% endfor %}
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
</div>
Is ii possible without creating a new field type?
solution
concerning #xabbuh's answer I found the solution at How to Customize Form Rendering in Symfony 3
I created a folder in my Bundle:
src/RoleBundle/Resources/views/form
and I put a new file (fields.html.twig) into it with this content
{%- block choice_widget_expanded -%}
<div {{ block('widget_container_attributes') }}>
{%- for child in form %}
<div class="input-group">
{{- form_widget(child) -}}
{{- form_label(child, null, {translation_domain: choice_translation_domain}) -}}
</div>
{% endfor -%}
</div>
{%- endblock choice_widget_expanded -%}
In the meantime I found another question which deals with this problem:
Overriding symfony radio widget
You can customise the rendering of your form using a custom form theme. You can so either on the project level or even do that just for a particular form (see How to Customize Form Rendering and How to Work with Form Themes for more information).
Your example looks like you need to override the choice_widget and choice_label
When I play with symfony is not very skilled, I don't often use this accepted solution to solve it
view:
<label class="layui-form-label">所属地市:</label>
<div class="layui-inline">
<select name="{{ form.cityId.vars.full_name }}" lay-verify="" id="{{ form.cityId.vars.id }}" lay-filter="case_city">
<option value="0">请选择</option>
{% if citylist is not empty %}
{% for list in citylist %}
<option value="{{ list.id is defined ? list.id : 0 }}">{{ list.areaName is defined ? list.areaName : '' }}</option>
{% endfor %}
{% endif %}
</select>
</div>
controller:
$caseReg = new CaseRegister();
$form = $this->createForm('Alarm\Component\Form\CaseRegisterType', $caseReg);
$form->handleRequest($request);
$citylist = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->findBy(array('pid'=>0,'status'=>0));
$caseType = $this->getDoctrine()->getRepository('AlarmComponent:CaseType')->findBy(array('status'=>0));
if ($form->isSubmitted()) {
$em = $this->getDoctrine()->getManager();
$param = $request->request->get('alarm_component_caseregister');
if($param['receiveId'] == 0)
{
$case = new CaseType();
$case->setCaseName($param['receiveName']);
$em->persist($case);
$em->flush($case);
$caseReg->setReceiveId($case->getId());
$caseReg->setReceiveName($case->getCaseName());
}
if($param['cityId'] != 0)
{
$city = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->find($param['cityId']);
$caseReg->setCityId($city);
}
if($param['subofficeId'] != 0)
{
$suboffice = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->find($param['subofficeId']);
$caseReg->setSubofficeId($suboffice);
}
$em->persist($caseReg);
$em->flush($caseReg);
return $this->redirectToRoute('case_register_index');
}
return $this->render('AlarmWebBundle:BackendBat\CaseRegister:new.html.twig', array(
'caseReg' => $caseReg,
'form' => $form->createView(),
'citylist' => $citylist,
'casetype' => $caseType
));
It is also can solve my problem, but when I was late to optimize this or they must be altered. But I hope this answer can solve your current problem.

Resources