Call to a member function createView() on null - twig

I am using symfony 5, within my Controller I have this :
$devisFrais = $devisRepository->getDevisPosteFDFrais($idDevis);
$formFrais = $this->createForm(DevisDisciplineQualifType::class, $devisFrais, [
'AT' => $AtNotAt,
'type' => 'FRAIS'
]);
return $this->render('devis.html.twig', [
'formFrais' => $formFrais->createView(),
]);
As $devisFrais is Null so formFrais is Null.
I can't create a form because I have this error : "Call to a member function createView() on null".
Is it possible to create a blank form, in this case how to manage it within the Twig

You are getting an error that your variable $formFrais is null.
What you need to do is to simply check your value for being null / empty,
with a ternary operator, and if it is give it is, execute the method, and if not, implement whatever logic you need after the ":".
You can do it in the Controller, no need to do any manipulation at the level of twig.
The basic logic is:
//...
return $this->render('devis.html.twig', [
'formFrais' => $formFrais ? $formFrais->createView() : $formFrais = "some_value",
]);

Related

Combine Search and checkbox filters in Vue js

I have to filter a list using a Search input field and als some Checkboxes (filter on a category).
I have both functionalities working independently.
The Search field
computed: {
getfilteredData() {
return this.experiences.filter(experience =>
experience.name.toLowerCase().includes(this.search.toLowerCase()) ||
experience.category.toLowerCase().includes(this.search.toLowerCase()
)
)
}
},
The Checkboxes
computed: {
getfilteredData() {
if (!this.checkedCategories.length)
return this.experiences
return this.experiences.filter(experience =>
this.checkedCategories.includes(experience.category))
}
},
How do I combine those filters? So they are working simultaneously?
combining both filters in succession will filter both as an AND statement
getfilteredData() {
return this.experiences.filter(experience =>
experience.name.toLowerCase().includes(this.search.toLowerCase()) ||
experience.category.toLowerCase().includes(this.search.toLowerCase()
)
).filter(experience =>
// if there are no checkboxes checked. all values will pass otherwise the category must be included
!this.checkedCategories.length || this.checkedCategories.includes(experience.category)
)
}
otherwise, you could combine them in one filter with (firstCondition || secondCondition) with the same logic you use above.
I saw your other question that got closed Write my Javascript more cleaner in my Vue js search functionality
where I think you could rewrite your function like this
experience => {
let reg = new RegExp(this.search, 'gi')
return reg.test(`${experience.name} ${experience.category}`)
}
using g means that your string can be in any position, but you must reconstruct your regex on each test otherwise you can end up with issues found here
Why am I seeing inconsistent JavaScript logic behavior looping with an alert() vs. without it?
using i means it will ignore casing so you don't need to worry about using toLowerCase()
thus your filter can be written like this in one statement
experience => {
let reg = new RegExp(this.search, 'gi')
// search input matches AND the checkbox matches
return reg.test(`${experience.name} ${experience.category}`) && (!this.checkedCategories.length || this.checkedCategories.includes(experience.category))
// search input matches OR the checkbox matches
//return reg.test(`${experience.name} ${experience.category}`) || (!this.checkedCategories.length || this.checkedCategories.includes(experience.category))
}

Using find{ } on a map where the whole map is evaluated not each element

I created some mixin methods. Code and example below:
URL.metaClass.withCreds = { u, p ->
delegate.openConnection().tap {
setRequestProperty('Authorization', "Basic ${(u + ':' + p).bytes.encodeBase64()}")
}
}
URLConnection.metaClass.fetchJson = {
delegate.setRequestProperty('Accept', 'application/json')
delegate.connect()
def code = delegate.responseCode
def result = new JsonSlurper().parse(code >= 400 ? delegate.errorStream : delegate.inputStream as InputStream)
[
ok : code in (200..299),
body: result,
code: code
]
}
example usage:
new URL("$baseUrl/projects/$name").withCreds(u, p).fetchJson().find {
it.ok
}?.tap{
it.repos = getRepos(it.key).collectEntries { [(it.slug): it] }
}
}
When I dont use find(), my object is, as expected, a map with those 3 elements. When I use find it is a Map.Entry with key ok and value true
which produces this error:
groovy.lang.MissingPropertyException: No such property: ok for class: java.util.LinkedHashMap$Entry
Possible solutions: key
It occured to me when I wrote this post that it was treated the map as an iterable and thus looking at every entry which I have subsequently verified. How do I find on the whole map? I want it.ok because if it's true, I need to carry it forward
There is no such method in Groovy SDK. Map.find() runs over an entry set of the map you call method on. Based on expectation you have defined I'm guessing you are looking for a function that tests map with a given predicate and returns the map if it matches the predicate. You may add a function that does to through Map.metaClass (since you already add methods to URL and URLConnection classes). Consider following example:
Map.metaClass.continueIf = { Closure<Boolean> predicate ->
predicate(delegate) ? delegate : null
}
def map = [
ok : true,
body: '{"message": "ok"}',
code: 200
]
map.continueIf { it.ok }?.tap {
it.repos = "something"
}
println map
In this example we introduced a new method Map.continueIf(predicate) that tests if map matches given predicate and returns a null otherwise. Running above example produces following output:
[ok:true, body:{"message": "ok"}, code:200, repos:something]
If predicate is not met, map does not get modified.
Alternatively, for more strict design, you could make fetchJson() method returning an object with corresponding onSuccess() and onError() methods so you can express more clearly that you add repos when you get a successful response and optionally you create an error response otherwise.
I hope it helps.

Twig custom function with parameters

I read twig documentation, but I am little confused about custom functions and filters. I understand how to add custom functions. But I don't understand how to write a function that accepts some parameters, may be also some optional parameters.
For example, I have following pseudo code for function named sqare.
$twig = new Twig_Environment($loader);
$function = new Twig_SimpleFunction('square', function () {
if param2 present?
return param1*param2;
else
return param1;
});
$twig->addFunction($function);
Now what I want is that, param1 should have a default value 1 and param2 should be optional. The square function will return the product of the two parameters. I also want that if user do not pass the second parameter then param1 will be returned, that is the first parameter will be returned. How can I implement this? Also, should I call the function in the twig template as {{ square(5, 10) }}?
You need to define the parameters in your closure.
Twig will pass the parameters accordingly
$function = new Twig_SimpleFunction('square', function ($param1, $param2 = null) {
return isset($param2) ? $param1 * $param2 : $param1;
});
Then you call this function in Twig with :
Only one param : {{ square(5) }}
Two params : {{ square(5, 2) }}

Search through related model in Yii

I have a problem with searching in Yii. I have two models: Teams and Workers. On website there is a page called 'Team Workers' where I want to display CGridView widget with searching that displays Workers from the team (team id is passed as a _GET parameter).
I did this in TeamsController:
public function actionWorkers($id)
{
$model = Teams::model()->findByPk($id);
$workers = Workers::model();
$workers->unsetAttributes();
if(isset($_GET['Workers']))
{
$_GET['Workers']['idTeam'] = $id;
$workers->attributes = $_GET['Workers'];
}
else {
$workers->attributes = array('idTeam' => $id);
}
$teamWorkers = $workers;
$this->render('workers', array(
'model' => $model,
'teamWorkers' => $teamWorkers
));
}
And in the view file:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'team-workers-grid',
'dataProvider'=>$teamWorkers->search(),
'filter' => $teamWorkers,
'columns'=>array(
'name',
'surname',
array(
'id' => 'idWorker',
'class' => 'CCheckBoxColumn',
'checked' => '$data->confirmer',
'selectableRows' => '2',
// 'headerTemplate' => '{item}'
)
),
)); ?>
I got the error:
CDbCommand nie zdołał wykonać instrukcji SQL: SQLSTATE[23000]: Integrity constraint
violation: 1052 Column 'idTeam' in where clause is ambiguous. The SQL statement
executed was: SELECT COUNT(DISTINCT `t`.`idWorker`) FROM `workers` `t` LEFT OUTER JOIN
`teams` `Team` ON (`t`.`idTeam`=`Team`.`idTeam`) WHERE ((idTeam=:ycp0) AND (Team.name
LIKE :ycp1))
When I dont set idTeam attribute - it works fine. It's pretty weird - at the regular CRUD admin page - idTeam attribute is passed and that works fine.
Hot to deal with it?
In Workers::search() you have something like
$criteria->compare('idTeam',$this->idTeam);
Change it to
$criteria->compare('t.idTeam',$this->idTeam);
i.e prefix sql attribute with t. if it is from current model or with relation name if from other table/model
Also instead of:
$workers->attributes = array('idTeam' => $id);
yould could keep it simpler with:
$workers->idTeam = $id;
You have defined the column idTeam in Team and Workers. By joining those tables you would have a duplicate ("ambiguous") column in the result. That's what the error message tells you.
To solve this you have to use an alias for one of the columns.

Drupal 6: Working with Hidden Fields

I am working on an issue i'm having with hooking a field, setting the default value, and making it hidden. The problem is that it is taking the default value, but only submitting the first character of the value to the database.
//Here is how I'm doing it
$form['field_sr_account'] = array( '#type' => 'hidden', '#value' => '45');
I suppose there is something wrong with the way that I have structured my array, but I can't seem to get it. I found a post, http://drupal.org/node/59660 , where someone found a solution to only the first character being submitted
//Here is the format of the solution to the post - but it's not hidden
$form['field_sr_account'][0]['#default_value']['value'] = '45';
How can I add the hidden attribute to this?
Have you tried using #default_value insted of #value?
Also if you're trying to pass some data to the submit that will not be changed in the form you should use http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html#value .
The answer was actually to set the value and the hidden attribute separately, then set the value again in the submit handler using the following format.
I'm not sure if it's all necessary, I suppose I probably don't need to assign it in the form alter, but it works, so I'm going to leave it alone...
$form['#field_sr_account'] = $club;
$form['field_sr_account'] = array( '#type' => 'hidden','#value' => $club);
}
}
/*in submit handler, restore the value in the proper format*/
$form_state['values']['field_sr_account'] = array('0' => array('value' => $form['#field_sr_account']));
An interesting solution from http://drupal.org/node/257431#comment-2057358
CCK Hidden Fields
/**
* Implementation of hook_form_alter().
*/
function YourModuleName_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && isset($form['#node'])) {
### Make a CCK field becoming a hidden type field.
// ### Use this check to match node edit form for a particular content type.
if ($form_id === 'YourContentTypeName_node_form') {
$form['#after_build'] = array('_test_set_cck_field_to_hidden');
}
}
}
function _test_set_cck_field_to_hidden($form, &$form_state) {
$form['field_NameToBeHidden'][0]['value']['#type'] = 'hidden';
$form['field_NameToBeHidden'][0]['#value']['value'] = 'testValue';
return $form;
}

Resources