drupal7 Filter content type based on session in view - drupal-7

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);
}
}
}

Related

Angular FormControl's material-checkboxes.component has selected values but this.controlValue is an empty array

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.

grid flickering with checkbox and edit method

My purpose is to translate interactively a checkbox action into a couple of values "0001" or "".
I placed this method on a table whose name is Notification.
// BP Deviation Documented
edit NoYesId provenWarranty (boolean _set = false, NoYesId _provenWarranty = NoYes::No)
{
NoYesId provenWarr;
;
// set value
if (_set)
{
if (_provenWarranty)
this.Func_Status = '0001';
else
this.Func_Status = '';
return _provenWarranty;
}
// read value
if (this.Func_Status == '0001')
return NoYes::Yes;
else
return NoYes::No;
}
This method is used by a Checkbox in a Form with this Table as a Datasource.
This method has been cached in the Notification datasource init() method.
Notification_ds.cacheAddMethod(tablemethodstr(Notification, provenWarranty));
My problem is that the Checkbox is constantly flickering, is there a way to avoid that ?
Update
The flickering appears inside the Checkbox design, but without
toggling it between checked or not.
This problem appears even if the Checkbox is connected to a basic
datasource field, not only if connected to an edit method.
It seems that the more fields there are in the datasource, the more
flickering I get.

How do I get a LazyComboBox to select an item from another page in Vaadin?

I am using Vaadin 7.5.5 and Viritin 1.35. I have implemented a LazyComboBox that is backed by a Spring Data JPA service call and repository.
My basic setup for the LazyComboBox is:
initList(
Site.class,
new FilterablePagingProvider() {
#Override
public List findEntities(int index, String name) {
return sitesService.findByName(name);
}
},
new FilterableCountProvider() {
#Override
public int size(String name) {
return sitesService.countByName(name);
}
},
PAGE_SIZE
);
This works great when I am typing in the combo box.
If I pick an item from the first page (page 0) I can then leave the combo box, come back to it, and click the drop down arrow again and the previously selected item is still selected.
However, if I choose an item from any page other than 0, then clicking the drop down arrow causes the selected item to become null and the user has to find the original item again.
I can post the details of the service and repository if needed but it isn't anything more complicated than a select * from table where name like '%' + name + '%'.
How do I keep the selected value in the combo box no matter what page was chosen?
Thank you.
I think you should call setNullSelectionAllowed(false); on this combo box.
Also, a solution to keep selected value after navigation can be to store it in a session value, then you'll be able to retreive it wherever you are. See Session wiki page

Cakephp:How to validate my select options so that it restricts duplication of options selected

I have a selection drop down menu, and I want the user to select two options for a field in the database. The problem is how do I make it to disallow duplication of select options, currently it's saving all options even when they are the same.
Code in my add.ctp for the select options is:
echo $this->Form->select("ProgrammeChoice.programme_code.0",$finals);
echo $this->Form->select("ProgrammeChoice.programme_code.1",$finals);
And the variable $finals is bringing the select options from another table in the database, it's in the controller and the code is:
$finals = array_merge($filtered_programs,$non_preq_programs);
So please, I want help to validate my select menu to deny duplicate selections on submission.
Create a custom validation rule and compare the values as described here: http://book.cakephp.org/2.0/en/models/data-validation.html#adding-your-own-validation-methods
In the validation method your data is stored in $this->data.
It should look similar to this:
public function compare($field1) {
if($field1 === $this->data['ProgrammeChoice']['programm_code']['1']) {
return false;
}
return true;
}

Filtering data using ajax observefield

I ve tried to implemented filtering data (list base on selected category) using dropdown with observefield and ajax pagination. I use session to remember selected category in order to keep pagination.
Here is my code (Cakephp 1.2)
In view :
echo $form->select('Category.id', $categories, null, array('id' => 'categories'),'Filter by Categories')
echo $ajax->observeField('categories' ,array('url' =>'update_category','update' => 'collectionDiv'));
In Controller:
if(!empty($this->data['Category']['id']))
{
$cat_id=$this->data['Category']['id'];
$filters=array('Collection.category_id' => $cat_id);
$this->set('collections', $this->paginate('Collection', $filters));
$this->Session->write($this->name.'.$cat_id', $category_id);
}
else
{
$cat_id=$this->Session->read($this->name.'.cat_id');
$filters=array('Collection.category_id' => $cat_id);
$this->set('collections', $this->paginate('Collection'));
}
The filter work as I wanted but the problem is when I select empty value('Filter by Category) it still remember last category session so I can't back to the default list (All record list without filter).
I've tried to make some condition but still not success. Is there another way? Please I appreciate your help. thank
hermawan
Perhaps I don't understand the question, but it looks to me like it might be worth changing:
else
{
$cat_id=$this->Session->read($this->name.'.cat_id');
$filters=array('Collection.category_id' => $cat_id);
$this->set('collections', $this->paginate('Collection'));
}
to:
else
{
$this->set('collections', $this->paginate('Collection',array()));
}
In effect your code appears to be doing this anyway. Check what the URL is at the top of the browser window after it has returned. Does it still contain pagination directives from the previous query?
You might want to review http://book.cakephp.org/view/167/AJAX-Pagination and make sure you've 'ticked all the boxes'.
I got it, It work as I hope now. I my self explain the condition and solution.
When I select category from combobox, then it render the page the code is :
If ($this->data['Category']['id']) {
$cat_id=$this->data['Category']['id'];
$this->Session->write($this->name.'.category_id', $category_id);
// I will use this session next when I click page number
$filters=array('Collection.art_type_id' => $category_id);
$this->set('collections', $this->paginate('Collection', $filters));
}else{
//if clik page number, next or whatever, $this->data['Category']['id'] will empty so
// use session to remember the category so the page will display next page or prev
// page with the proper category, But the problem is, when I set category fillter to
// "All Category" it will dislpay last category taked from the session. To prevent it
// I used $this->passedArgs['page']. When I clik the page paginator it will return
// current number page, but it will be empty if we click dropdown.
if (!empty($this->passedArgs['page']) {
$cat_id=$this->Session->read($this->name.'.category_id');
$filters=array('Collection.category_id' => $cat_id);
$this->set('collections', $this->paginate('Collection',$filters));
}else{
$this->set('collections', $this->paginate('Collection'));
}
}
From this case, I think that observefield will not send passedArg as we get from url such from ajax link or html->link. I hope this will usefull to anybody

Resources