Symfony 4 How to add an attribute to a twig using jquery? - twig

I'm trying to do a form with symfony 4. It works fine. But I have a problem.
I have a field to write a comment. By default, it's not required.
However, I would like to change this using jquery.
This is what I tried to do.
Here, it's my twig:
<div class="information" id="informationForm">
{{ form_row(recordForm.category) }}
{{ form_row(recordForm.information) }}
{{ form_label(recordForm.comment) }}
{{ form_widget(recordForm.comment, {'attr': {'class': 'comment'}}) }}
{{ form_errors(recordForm.comment) }}
<button id="add_information_button" class="btn btn-primary">Ajouter un renseignement</button>
<button id="count_div" class="btn btn-primary">Compter</button>
<button class="remove_information_button btn btn-primary">Supprimer un renseignement</button>
</div>
Here it's the javascript:
$('.information')
.on("change", ".record_to_information_form_information", function (event) {
event.preventDefault();
var $commentState = $(this).find('option:selected').data('comment')
//Test: to know if i received the attribute
console.log($commentState)
if($commentState===false){
//the field isn't required
// {{ form_widget(recordForm.comment, {'attr': {'required': 'false'}}) }}
}else{
//the field is required
// {{ form_widget(recordForm.comment, {'attr': {'required': 'true'}}) }}
}
})
;
Do you have any suggestions?

You can toggle required property value from your jQuery code.
I assume that data-comment attribute has type boolean and it's always set, so your toggle statement can look as follows:
$('.information')
.on("change", ".record_to_information_form_information", function (event) {
event.preventDefault();
var $commentState = $(this).find('option:selected').data('comment');
//Test: to know if i received the attribute
console.log($commentState);
$('.comment').prop('required', $commentState);
});
If you need to do something else in your if-else statement, you can just leave your condition as you provided in sample:
if ($commentState === false) {
//the field isn't required
$('.comment').prop('required', false);
} else {
//the field is required
$('.comment').prop('required', true);
}

Related

Show select field based on some other select option in flask

I am creating a flask form where I need to show a dropdown based on some other dropdown select field in Flask. I was able to do it with HTML, but finding it difficult to do the same in Flask form.
routes.py :
class RegistrationForm(FlaskForm):
category = SelectField('Category', choices = [('Clothes', 'Clothes'), ('Watch', 'Watch')])
subcategory = SelectField('Sub Category', choices = [('USPA', 'USPA'), ('LEE', 'LEE'), ('FOSSIL', 'FOSSIL'), ('TITAN', 'TITAN')])
submit = SubmitField('Register')
HTML :
<form action="" method="post">
{{ form.hidden_tag() }}
<p>
<p>
{{ form.category.label }}<br>
{{ form.category }}<br>
{% for error in form.category.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.subcategory.label }}<br>
{{ form.subcategory }}<br>
{% for error in form.subcategory.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.submit() }}</p>
</form>
I want mapping link this :
Clothes : USPA, LEE
Watch : FOSSIL, TITAN
But in the form I am getting all the options. I need subcategory based on selected category.
Since this is dynamic functionality on the client side you will need to use Javascript.
Personally I think the easiest way to do this is pre configure your flask form statically:
class RegistrationForm(FlaskForm):
category = SelectField('Category', choices = [('Clothes', 'Clothes'), ('Watch', 'Watch')])
subcategory_clothes = SelectField('Sub Category', choices = [('USPA', 'USPA'), ('LEE', 'LEE')], validators=[Optional()])
subcategory_watches = SelectField('Sub Category', choices = [('Titan', 'Titan'), ('Fossil', 'Fossil')], validators=[Optional()])
submit = SubmitField('Register')
And then display either one or the other combo boxes dependent upon the value of the initial combo box, using Javascript if statement. You will need a javascript event hook to detect changes to category, or use a framework such as Vue.js.
An example of javascript hook is here https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onchange
You can add a javascript function, in HTML, to show either box depending on the value of the other checkbox:
<script>
function myFunction() {
let box_value = document.getElementById("category").value;
if (box_value === "Clothes") {
document.getElementById("subcategory_clothes").style.display = "initial"
document.getElementById("subcategory_watches").style.display = "none"
} else {
document.getElementById("subcategory_clothes").style.display = "none"
document.getElementById("subcategory_watches").style.display = "initial"
}
}
</script>
And you can add a render_keyword argument in Python so that it populates the event hook in HTML:
category = SelectField('Category', choices = [('Clothes', 'Clothes'), ('Watch', 'Watch')], render_kw={'onchange': "myFunction()"})

How do I use req.flash() with nunjucks?

I am using connect-flash to pass the flash message. In my controller, I am using the following code if (!req.user) {
req.flash("error_msg", "User not found !!");
return res.redirect(307, '/');
}
In my view, I tried
{{ error_message }}
{{ req.flash('error_message') }}
{{ req.flash.get('error_message') }}
But none of it works. What's the current syntax to parse the flash message in nunjucks ?
First of all you have to install "express-flash" and put below code in app.js
app.js
const flash = require('express-flash');
In Your Controller put below code when you want to pass message
req.flash('error_msg', "User not found !!");
return res.redirect(307, '/');
Put below code in your view file where you want to display message
<% if (typeof messages.error_msg !='undefined') { %>
<p class="error"><%= messages.error_msg %></p>
<% } %>
For anyone facing the same problem you can access the variable using {{ req.session.flash.error_msg }}
If you are using express js and nunjucks as template this is what I have done
in app.js
const flash = require('express-flash');
app.use(flash());
in Routes/controller code
try {
await User.deleteOne({_id:req.params._id}).exec()
req.flash("success_msg", "User deleted");
return res.redirect('/admin/users')
}
in Layout or view file
{% if messages.success_msg %}
<div class="alert alert-success" role="alert">
{{ messages.success_msg }}
</div>
{% endif %}
With connect-flash package, you cannot directly use req.flash in template engine. You need to add a middleware that adds the flash message to the res.locals which can be accessed in template rendering.
Here is a short code snippet.
// this part should be before all the request resolver.
// adding flash function to response locals
app.use((req,res,next)=>{
res.locals.flash = (arg) => { return req.flash(arg) };
next();
});
// request resolver
app.get("/",(req,res)=>{
req.flash("info","show me");
res.render("index.njk",{});
});
app.listen(8080,()=>{...})
In nunjucks file:
<h3>{{ flash("info") }}</h3>

How to get user_token value from the URL

In an OpenCart framework version, 3.0.2.x, for the
URL = http://localhost/moreshop/admin/index.php?route=account/apisync&user_token=FARboCmeZHqQl8bITE3SRTenJscadbYc
I need to get the URL value from the parameter user_token that is written in the .twig format
Previously with OpenCart version 2.3.x.x, this was written in the .tpl file as
<input type="hidden" name="token" id="token" value="<?php echo $_GET['token']; ?>"/>
I had tried to assign the value =
{{ app.request.query.all }}
{{ app.request.query.get('user_token') }}
{{ app.request.get('user_token') }}
{{ _GET.user_token }}
But all the above value assigned with null. So how do I get the value of the user_token and assign into value=?
You should define it in your controller file:
$data['user_token'] = $this->session->data['user_token'];
Than you can call it in twig file:
<input type="hidden" name="User_token" id="user_token" value="{{ user_token }}"/>
you also can try call it {{ _GET.token }}
Alternative Solution: (This is not the exact solution to the question posted )
I had used JavaScript to catch hold of the user_token value and then pass it to AJAX in order to redirect to the particular URL
function getUrlParameter(sParam) {
var sPageURL = decodeURIComponent(window.location.search.substring(1)),
sURLVariables = sPageURL.split('&'),
sParameterName, i;
for (i = 0; i < sURLVariables.length; i++) {
sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] === sParam) {
return sParameterName[1] === undefined ? true : sParameterName[1];
}
}
};
var user_token = getUrlParameter('user_token');
console.log(user_token);
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>

Nodejs use method in view

For example,In my Nodejs app,I have a router:
exports.test=function(req,res){
res.render('./admin/test.jade',{html:[a,b,c]);
}
And I have Underscore.js
In my view test.jade:
-var _und=require('Underscore.js')
....
div
-_und.each(html,function(m))
span m
....
But I got error.This shows that,the Underscore.js is just be used as a server-side method,how can I use a server-side method in view?
You don't need to require underscore from a view. To view you should send just data (it means that in idea case you should not use underscore there at all). But if you would like, you can still send underscore like a function to view:
exports.test = function(req,res) {
res.render('./admin/test.jade',{ html: [a,b,c], _ : require("underscore") });
};
or like this:
exports.test = function(req,res) {
var underscore = require("underscore");
res.render('./admin/test.jade', { html : [a,b,c], _ : underscore });
}
After in your view you can access to that like this:
div
-_und.each(html,function(m))
span m
You can get inspired from my nodejs github markdown project (http://bit.ly/1aOAG35). There is used underscore for layouting and I'm using it as well in templates:
{{# onlyblogs.forEach(function(current){ }}
<li>
{{ current.title }}
{{# if (current.description){ }}
<span>{{ current.description }}</span>
{{# } }}
<span>{{ current.category }}</span> in <date>{{ current.date }}</date>.
</li>
{{# }); }}
Hope that it helped.

Flashdata not render in view

im try print an alert report before a submit form.
The constroller check that entity was valid and inform the result:
$estado = Array();
if(count($errors) > 0){
$estado['alert'] = 'alert-error';
$estado['message'] = $errors->get(0);
}else{
$estado['alert'] = 'alert-success';
$estado['message'] = "Usuario creado correctamente";
}
$this->getRequest()->getSession()->getFlashBag()->add('status',$estado);
return $this->redirect($this->generateUrl('alta_usuario'));
So, in the view:
{% if app.session.flashbag.has('status') %}
<div class="alert {{ app.session.get('status').alert }}">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ app.session.get('status').message }}
</div>
{% endif %}
But Symfony fails with the next message:
Impossible to access an attribute ("alert") on a NULL variable ("")
In the profiler the Flashdata is:
status : [{"alert":"alert-error","message":{}}]
Two questions:
1) Why "message" is null ? the entity has an error and $errors->get(0) should be get the first error ?
2) Why can't access the $estado values from the view ?.
Any ideas ?.
This question is much similar as below link.
You can find the answer at
Am I using the Symfony flash variables the wrong way?

Resources