I have created a new module in Odoo for helpdesk and I have 2 problems that I can't seem to fix or find information on so need some help.
I created a status bar (code):
state = fields.Selection({('new','New'), ('open','In Progress'), ('closed','Closed')}, "Status")
_defaults = {
'state': 'new'
}
<header>
<field name="state" widget="statusbar" statusbar_visible="new,open,closed" clickable="True"/>
Even thought I have stated "new, open, closed" it is showing in Odoo as open,new, closed.
I set the state default as new, even though I am not getting any errors, when I click on create it shows state as blank.
Any ideas on how to fix these issues?
When you declared your field you gave it a set of options instead of a list of options. Sets in Python doesn't keep the information about items order, but lists do. For your declared order to be respected you just need to replace the set literal by a list literal:
state = fields.Selection(
[('new','New'), ('open','In Progress'), ('closed','Closed')],
"Status",
)
You can remove statusbar_visible from your view.
As for your second problem (with the default value) Emipro Technologies is correct. You need to declare the default value as an argument on your field:
state = fields.Selection(
[('new','New'), ('open','In Progress'), ('closed','Closed')],
default='new',
string="Status",
)
Your fields declaration seems that it's Odoo-8 code, in V8 _defaults is not there you need to write as below,
state = fields.Selection({('new','New'), ('open','In Progress'), ('closed','Closed')},"Status", default='new')
And there is no more logic to set sequence in status bar but then also try this,
<form string="String" version="7.0">
<header>
<field name="state" widget="statusbar" statusbar_visible="new,open,closed" clickable="True"/>
</header>
</form>
Related
I have an Angular form I've built that consists of a single material-checkboxes component. I have two copies of this component, one is static and one is dynamic. The only difference is that the dynamic version gets its control values from an API call. Both of these examples have one or more options defaulted as checked when the controls initialize.
The issue I have is that the dynamic one's model is out of sync with its view as long as its left unchanged (ie, if I don't click on any of the checkbox controls to select or unselect them). Once I click on one of the checkboxes, the model updates to sync with the view.
I can tell this because I can submit the static version and get expected results (the defaulted items are posted as values as expected). However, when I submit the dynamic one, I get an empty post.
Here is what the component looks like with the defaulted values before I submit it to see the submitted form data:
And here is the resulted submitted values (as expected):
By way of comparison, here is the same control (material-checkboxes.component.ts) but built using an external datasource to feed in the titleMap and also has defaulted values.
And here is the result after submit of the above form:
So, as the screencaps indicate, The manually created one works as expected and submits the form containing the defaulted values. However, the component with the dynamically generated values, even though the view shows it to have selected default options, submits as EMPTY.
Expected: this.controlValue = ['12', 'd4']
Actual:
onInit > this.controlValue = ['12', 'd4']
After updateValue method > this.controlValue = undefined // But the view is unchanged from the init
However, I can get it to submit data as expected, if I manually change any of the values, even if i set them exactly as they were defaulted. Its as if the form data is not being set until manually clicking on the options.
Here is a snippet from the template that holds the component:
<mat-checkbox
type="checkbox"
[class.mat-checkboxes-invalid]="showError && touched"
[class.mat-checkbox-readonly]="options?.readonly"
[checked]="allChecked"
[disabled]="(controlDisabled$ | async) || options?.readonly"
[color]="options?.color || 'primary'"
[indeterminate]="someChecked"
[name]="options?.name"
(focusout)="onFocusOut()"
(change)="updateAllValues($event)"
[required]="required"
[value]="controlValue">
Update: I found that the issue was that the form control's value is not updated before leaving the syncCurrentValues() method called just after the setTitleMap hostlistener. Adding a call to this.updateValue() in syncCurrentValues() resolves it and the model and view are back in sync. However, there is a problem, but first, here is the code that resolves the issue when there is a default value set in the this.options data:
#HostListener('document:setTitleMap', ['$event'])
setTitleMap(event: CustomEvent) {
if (event.detail.eventName === this.options.wruxDynamicHook && isRequester(this.componentId, event.detail.params)) {
this.checkboxList = buildTitleMap(event.detail.titleMap, this.options.enum, true, true, this.options.allowUnselect || false);
// Data coming in after ngInit. So if this is the first time the list is provided, then use the defaultValues from the options.
const value = this.setDefaultValueComplete ?
this.jsf.getFormControl(this)?.value || [] :
[].concat(this.options?.defaultValue || []);
this.syncCurrentValues(value);
// Set flag to true so we ignore future calls and not overwrite potential user edits
this.setDefaultValueComplete = true;
}
}
updateValue(event: any = {}) {
this.options.showErrors = true;
// this.jsf.updateArrayCheckboxList(this, this.options.readonly ? this.checkboxListInitValues : this.checkboxList);
this.jsf.updateArrayCheckboxList(this, this.checkboxList);
this.onCustomAction(this.checkboxList);
this.onCustomEvent(this.checkboxList);
this.jsf.forceUpdates();
if (this.jsf.mode === 'builder-properties') {
this.jsf.elementBlurred();
}
}
syncCurrentValues(newValues: Array<any>): void {
for (const checkboxItem of this.checkboxList) {
checkboxItem.checked = newValues.includes(checkboxItem.value);
}
this.updateValue(); // Fixed it. Otherwise, the checked items in titlemap never get synced to the model
}
The call to updateData() above fixes the issue in that case. However, when there are no default values in the options data and the checkbox data is loaded externally from an API call that executes after the ngOnInit has fired, I have the same issue. this.controlValue is empty after ngOnInit despite that the view has updated to show checked checkboxes. The model has made that happen through the setTitleMap() method but the controlValue still logs as an empty array.
I'm currently working on a springboot/reactjs project. I'm using the react select library to set a multi select input in one of my forms but I could not get the selected values here's some code to make it a bit clearer.
these are my options generated dynamically from the database each option has the webService Id as a value
this is my select input, I need to get the selected values "Ids" and then call the method that retrieves the webservices from the database and then assign the list of webServices to my newApplicationData.webservices
this is the get web service function
Update : I kind off found a solution to my problem : on the onChange prop I used this
onChange={(selectedOptions) => {
const state = this.state;
state.selectedWebServices = [];
selectedOptions.forEach((option) => {
this.getWS(option.value);
state.selectedWebServices.push(this.state.getWSData);
});
state.newApplicationData.webServices =
state.selectedWebServices;
this.setState(state);
}}
and then I found out another problem: even if I select two deffrent options the list of selected options only gets one duplicated option????!!!!
I have implemented react-select to allow entering tags based on auto-complete suggestions and/or inserting new ones.
My implementation is as follows:
import Select from 'react-select';
...
<Select.AsyncCreatable
className='add-tags'
clearable={!!selectionTags}
placeholder={'add more'}
name="form-field-name"
value={selectionTags}
onChange={setSelectionTags}
loadOptions={loadOptions}
promptTextCreator={(label)=>`add new tag: ${label}`}
inputProps={inputProps}
multi
/>
When selectionTags is the list of tags that have already been selected, setSelectionTags is a function that adds a new selected item to that list, and loadOptions holds the list of autocomplete suggestions.
Problem is that if I type "ta" and I have "tag1" as one of the available completions, then choosing it will empty the list of suggestions but leave the "add new tag: ta" entry displayed.
Any idea why it's not being removed as well?
Thanks!
Following this thread on React-Select github:
https://github.com/JedWatson/react-select/issues/1663
I ended up working round it by adding the following options:
ref={s => (selectRef = s)} // store a reference to the select instance
onChange={tags => {
selectRef.select.closeMenu(); // close the entire menu
selectRef.select.setState({
isFocused: false, // remove focus from new tag option
});
setSelectionTags(tags); // call the add tags method with the new set of tags
}}
I have created a custom type with multiple fields.
1 field is a checkbox to "show for all people"
2nd field is a textfield ( you can add multiple textfields ) for adding a code.
I created a view where all those content types are being shown in a page. ( this works )
But now:
When a person enters the site, he has to insert a code. This code is saved into a cookie because it needs to be remembered for about 2 weeks.
So I can't use the contextual filters.
If the checkbox "show for all people" is checked, this block is shown.
if the checkbox "show for all people" is unchecked, this block is hidden, except for people who came in without a code, or if the code is one of the values that was inserted in the 2nd field.
I don't wan't to use views php_filter. But I have no clue how to proceed with this problem.
I tried some solutions on the web to create a custom filter, but the problem here is, that we can't access the form values.
I found a solution, but I'm not sure if this is the correct drupal way.
I used the hook_node_view function to get all nodes that are printed on that page. I check if the code that was inserted into a cookie with the codes that are allowed ( created in the text fields of the content type )
function code_node_view($node, $view_mode, $langcode) {
if ($node->type == 'winning_codes') {
$code = _code_read_cookie('code');
$winning_codes = (!empty($node->field_winning_codes['und'])) ? $node->field_winning_codes['und'] : array();
$winning_codes = array_map(function ($ar) {
return $ar['value'];
}, $winning_codes);
if (!empty($code) && (!in_array($code, $winning_codes))) {
hide($node->content);
}
}
}
I want to prepopulate an input field from my controller:
Here is the input field:
<input class="form-control" type="text" name="partnerName" placeholder="Completeaza numele partenerului" ng-model="partnerNameModel.field" required validate-field="partnerNameModel">
In my controller,
If I do this:
partnerNameModel.field = 'test';
I get the following error:
TypeError: Cannot set property 'field' of undefined
So, I had to do it like this:
$scope.partnerNameModel = {field: 'dsad'};
I this good practice?
Is there a better way to prepopulate fields?
You can create the object partnerNameModel by doing
$scope.partnerNameModel = {}
at the top of your controller then you can use the dot syntax to set values like
$scope.partnerNameModel.value = "foo"
$scope.partnerNameModel.bar = "lemons"
This is how I personally work with objects in Angular
When you are dealing with an input that has a placeholder, it makes sense to put no default value.
However, the object you are using must be created or it will be a big pain in the ass.
I recommend that you simply use:
$scope.partnerNameModel = {};
Make sure to initialize your fields that don't use a non-empty default value (a dropdown as an example).
$scope.partnerNameModel = {
myDrop: $scope.myList[0]
};