Odoo 12: Pass data to Qweb report template - odoo-12

I want to send dictionnary to my qweb report template but it gives me error like this:
TypeError: 'NoneType' object is not subscriptable
Error to render compiling AST
TypeError: 'NoneType' object is not subscriptable
Template: 1364
Path: /templates/t/t/t/t/div/h1/t
Node:< t t-esc="data['this']"/>
Here is my .py code located iny models folder:
class ReportMenumenu(models.AbstractModel):
_inherit = "my.model"
#api.model
def _get_report_values(self, docids, data=None):
data = {'this': 'test'}
return {
'doc_ids': self.ids,
'doc_model': self.model,
'data': data,
}
And here is the report template that take the data:
<odoo>
<template id="my_module.report_name">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="
<h1>
<t t-esc="data['this']"/>
</
</div>
</t>
</t>
</t>
</template></odoo>
Can you help me? Thank you.

Related

AG-GRID angular material component not working when using external html template

I am trying to implement an angular material select component in the AG-GRID as per the example described here
However when I click on the cell that should make the select appear, it does not appear and in the console the following error appears:
core.js:4002 ERROR TypeError: Cannot read property 'element' of undefined
at mat-select.component.ts:37
This corresponds to the following method in the MatSelectComponent:
// dont use afterGuiAttached for post gui events - hook into ngAfterViewInit instead for this
ngAfterViewInit() {
window.setTimeout(() => {
this.group.element.nativeElement.focus();
});
this.selectFavouriteVegetableBasedOnSelectedIndex();
}
This component has been copied exactly from the example given, except that I put the template and styles in their own HTML/SCSS files respectively.
#Component({
selector: 'radio-cell',
template: './mat-select.component.html'
styles: ['./mat-slect.component.scss']
})
However, when I include the HTML template within the component like in the example it works!
#Component({
selector: 'radio-cell',
template: `
<mat-card>
<div class="container" #group tabindex="0" (keydown)="onKeyDown($event)">
<mat-form-field>
<mat-select panelClass="ag-custom-component-popup" [(ngModel)]="favouriteVegetable">
<mat-option *ngFor="let vegetable of vegetables" [value]="vegetable">
{{ vegetable }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</mat-card>
`,
styles: ['./mat-slect.component.scss']
})
Is there any explaination of this behaviour or way around putting all this HTML into the component?
EDIT 1:
The component includes the 'group' template reference variable in the component like below, so should it not be available to the ngAfterViewInit() method?
#ViewChild("group", { read: ViewContainerRef, static: true })
public group;
Your error Cannot read property 'element' of undefined comes from the fact that this.group is undefined because angular tries to query it in the template but doesn't find it <div class="container"#grouptabindex="0" (keydown)="onKeyDown($event)">

AEM 6.3 - Sling Model not working

I am using a very basic Sling Model class which is not working at all. This is the class:
package com.aem.sites.models.test;
import org.apache.sling.models.annotations.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import org.apache.sling.api.resource.Resource;
#Model(adaptables=Resource.class)
public class TestModel {
final static Logger logger = LoggerFactory.getLogger(TestModel.class);
private String email;
#PostConstruct
public void init() {
logger.info("=====================================================================inside init method");
email = "something#something.com";
}
public String getEmail() {
return email;
}
}
I have also included the package in the section like this:
I also looked for the Sling Model class here http://localhost:4502/system/console/status-adapters
and found it's entry like this:
Adaptable: org.apache.sling.api.resource.Resource
Providing Bundle: org.apache.sling.models.impl
Available Adapters:
* com.aem.sites.models.test.TestModel
What's more surprising to me is the Sling Model class in the package com.aem.sites.models.header is being called properly.
I don't know what's wrong.
Thanks in advance
Sharing the HTL class:
<sly data-sly-use.bannerObj=com.aem.sites.models.test.TestModel">
<section id="banner"
style="background-image: url('/content/dam/aem-site/banner.jpg')">
<div class="inner">
<h2>Today's temperature is</h2>
<p>
${bannerObj.email}
</p>
<ul class="actions">
<li>Sign Up</li>
<li>Learn More</li>
</ul>
</div>
</section>
</sly>
By not working I mean nothing is happening. No errors or any logs are appearing in the error.log file.
The only issue I see is a syntax error, the data-sly-use attribute's value is not enclosed in quotes properly.
<sly data-sly-use.bannerObj="com.aem.sites.models.test.TestModel">
<section id="banner"
style="background-image: url('/content/dam/aem-site/banner.jpg')">
<div class="inner">
<h2>Today's temperature is</h2>
<p>
${bannerObj.email}
</p>
<ul class="actions">
<li>Sign Up</li>
<li>Learn More</li>
</ul>
</div>
</section>
</sly>
Due to which the HTL file might not have compiled and would have output the entire HTL as is without compiling.
You can check from http://localhost:4502/system/console/status-slingmodels which Sling models are available in your instance and to what resources they are bound.
I would make sure my models are listed and then check for other kind of errors, like typos as mentioned in the comment above.

Error: Uncaught (in promise): Error: formGroup expects a FormGroup instance. Please pass one in

I am creating a form in Angular 2 with an input with autocompletion. I would like to get the data of the autocompletion services in this input but when, I am running it I got this error:
ERROR Error: Uncaught (in promise): Error: formGroup expects a FormGroup instance. Please pass one in.
app.ts
export class AppComponent {
#Input('group')
public group: FormGroup;
formatList(data: any):string {
return `<span>${data["value"]}</span>`;
}
searchResult(search:string):Observable<any> {
return this.autoCompleteService.search(search);
}
sendInitiator(item) {
....
}
constructor(
private http: Http,
private autoCompleteService:AutoCompleteInitiatorService
) {
this.searchResult = this.searchResult.bind(this);
this.autoCompleteService = autoCompleteService;
}
}
app.component
<form id="Form" class="form-horizontal" novalidate="novalidate">
label for="name" class="col-sm-2 control-label">Name :</label>
<div class="col-sm-4" [formGroup]="group">
<div class="input-group-item">
<input class="input"
auto-complete require
formControlName="initiator"
[source]="searchResult"
(valueChanged)="sendInitiator($event)"
name="initiator"
auto-complete-placeholder="Select One"
value-property-name="id"
display-property-name="value"
min-chars="2" [list-formatter]="formatList" />
</div>
<form>
Any help/pointing me in the right direction would be great! Thanks!
You need to initiate form with formBuilder, like this plunker
this.group = this.formBuilder.group({
initiator: ''
})

Call a Method From Inside dom-repeat in Polymer

I'm having this situation where I need to call a method from the dom-repeat. Below is my code
<template is='dom-repeat' items="[[_dataArray]]" as="rowItem">
<template is='dom-repeat' items="[[_objectArray]]" as="columnItem">
<template>
<span>[[_getColumnItemValue(rowItem, columnItem)]]</span>
</template>
</template>
</template>
and in my _getColumnItemValue method, I want to get the value for an object with key specified by the columnData attribute.
Like rowData[columnData]
_getColumnItemValue: function(rowData, columnData) {
return rowData[columnData];
}
My problem is the method _getColumnItemValue is not being called. Is there any better way to do achieve this?
If your code is exactly as you pasted, then you have one too many <template> tags.
<template is='dom-repeat'>
<template is='dom-repeat'>
<span></span>
</template>
</template>
The innermost template must be removed. You are rendering that instead of the <span>.
Finally i was able to make this thing working. Not exactly in this case, but in another project, with exact same logic. The only change was my _objectArray was not an array of strings, it was an array of objects. So the code will look like this:
<template is="dom-repeat" items="{{tableData}}" as="rowData">
<tr>
<template is="dom-repeat" items="{{headers}}" as="columnData">
<td>
<template is="dom-if" if="{{checkType(columnData, 'check')}}">
<paper-checkbox disabled="{{getAttributeValue(columnData, 'disabled')}}" checked="{{getRowData(rowData, columnData)}}" on-change="checkBoxSelected"></paper-checkbox>
</template>
<template is="dom-if" if="{{checkType(columnData, 'led')}}">
<led-indicator on="{{!getRowData(rowData, columnData)}}"></led-indicator>
<span style="display: none;">{{getRowData(rowData, columnData)}}</span>
</template>
<template is="dom-if" if="{{checkType(columnData, 'link')}}">
{{getRowData(rowData, columnData)}}
</template>
<template is="dom-if" if="{{checkType(columnData, 'text')}}">
<span>{{getRowData(rowData, columnData)}}</span>
</template>
</td>
</template>
</tr>
</template>
See the method getRowData
getRowData: function (row, column) {
return row[column.key];
},
and
checkType: function (columnData, type) {
var isType = false;
isType = columnData.type.toLowerCase() == type.toLowerCase();
return isType;
},
This is for a table, which can dynamically add or remove rows and columns and show different type of elements like, a text, link, checkbox some of my custom controls like led-indicator etc.
The logic behind is, the headers array will be used to generate the table columns, this array contains objects of structure
{
name: 'Popular Name',
key: 'PopularName',
type: 'text'
}
and table data contains array of object, which contains the key specified in the headers array.
Hope this may be useful for some one.

Angular 2 form validation, hasError is not a function

i try to make a validation for my input fields.
this is a piece of code that I used:
DepartmentComponent
import {
FORM_DIRECTIVES,
FormBuilder,
ControlGroup,
Validators ,
AbstractControl
} from 'angular2/common';
#Component({
selector: 'my-departments',
providers: [HTTP_PROVIDERS, DepartmentService],
directives: [FORM_DIRECTIVES, Alert],
styleUrls: ['app/department.component.css'],
templateUrl: 'app/department.component.html',
pipes:[SearchPipe]
})
export class DepartmentComponent implements OnInit {
myForm: ControlGroup;
departmentName: AbstractControl;
departmentLocation: AbstractControl;
constructor(private _router: Router, private _departmentService: DepartmentService, fb: FormBuilder) {
this.myForm = fb.group({
'departmentName': ['', Validators.required],
'departmentLocation': ['', Validators.required]
});
this.departmentName= this.myForm.controls['departmentName'];
this.departmentLocation= this.myForm.controls['departmentLocation'];
}
DepartmentComponent template
<form [ngFormModel]="myForm"
(ngSubmit)="addDepartment(newItem)" [hidden]="!showAddView" align="center">
<div>
<label for="editAbrv">Department name:</label><br>
<input type="text" [(ngModel)]="newItem.departmentName" [ngFormControl]="myForm.controls['departmentName']" >
<div *ngIf="departmentName.hasError('required')" class="ui error message"><b style="color:red;">Name is required</b></div>
</div>
<div>
<label for="editAbrv">Department Location:</label><br>
<input type="text" [(ngModel)]="newItem.departmentLocation" [ngFormControl]="myForm.controls['departmentLocation']" >
<div *ngIf="departmentLocation.hasError('required')" class="ui error message"><b style="color:red;">Location is required</b></div>
</div>
<div>
<button type="submit" class="ui button">Submit</button>
<button><a href="javascript:void(0);" (click)="showHide($event)" >
Cancel
</a></button>
</div>
</form>
The problem is that I got an error: .hasError is not a function. hasError function is in my html file (which you can see) I really don't see where I'm wrong. I did everything like is described in tutorial, but can't figure out why is this happen. Thanks for advice!
you should use *ngIf="myForm.controls['departmentLocation'].hasError('required')"
or any better luck with
this.departmentName= this.myForm.controls.find('departmentName'); ?
In place of hasError you should use errors
i.e it should be
myForm.controls['departmentLocation'].errors['required']
i.e with *ngIf
*ngIf="myForm.controls['departmentLocation'].errors['required']"
This is similar to another answer I've provided here: Form Builder with hasError() for validation throws an error of ERROR TypeError: Cannot read property 'hasError' of undefined.
The gist is that TypeScript getter's can be used to solve this in a clean way.
In your component class:
get departmentLocation() {
return this.myForm.get( 'departmentLocation' );
}
In your component template:
<input type="text" formControlName="departmentLocation">
<p class="ui error message" *ngIf="departmentLocation.hasError('required')">Department location is required</p>
Also important to note that using ngModel with Reactive Forms in Angular 6+ is depracated, so it's been removed from the examples above.
i was getting compilation error for using
loginForm.get('email').hasError('required')
This fixed it
loginForm.get('email')?.hasError('required')
use it like this
<mat-error *ngIf="!loginForm.get('password')?.hasError('required')
&& loginForm.get('password')?.hasError('whitespace')">