Is there a way to dynamically toggle pagination in ag-grid?
The API doesn't seem to explicitly support it.
What's the best workaround?
As far as I know there is not nativly something available. But the best workaround would be to set the pagination attribute in the gridOptions and then have the entire table re-render. In Angular this would looks something like this: https://plnkr.co/edit/aRPG3X6sTeuKcqj1?open=app%2Fapp.component.ts
For the template:
<button (click)="togglePagination()">Toggle Pagination</button>
<ng-container #container >
</ng-container>
<ng-template #table>
<ag-grid-angular
style="width: 100%; height: 100%;"
class="ag-theme-alpine"
[columnDefs]="columnDefs"
[autoGroupColumnDef]="autoGroupColumnDef"
[defaultColDef]="defaultColDef"
[suppressRowClickSelection]="true"
[groupSelectsChildren]="true"
[rowSelection]="rowSelection"
[rowGroupPanelShow]="rowGroupPanelShow"
[pivotPanelShow]="pivotPanelShow"
[enableRangeSelection]="true"
[rowData]="rowData"
[gridOptions]="gridOptions"
(gridReady)="onGridReady($event)"
></ag-grid-angular>
</ng-template>
and the toggle function is doing the redraw
public gridOptions: GridOptions = {
pagination: true,
}
public togglePagination() {
this.gridOptions = {pagination: !this.gridOptions.pagination};
this.outletRef.clear();
this.outletRef.createEmbeddedView(this.contentRef);
}
You didn't specify if you use a framework or the native JS. But the redraw approach works in every framework and also natively just with a different syntax
Related
I am trying to implement selectize javascript library. It works but my question is how do I disable the sifter option. The problem is by default sifter option is enabled and if I have words like Asset in the option, it will be filtered to become et.
I tried with below but doesn't work:
score: function () {
return function () {
return 1
}
}
Selectize is very dependent on sifter, I don't see a easy way to disable that, and I think if you do that, you get rid of most of (maybe the entire) selectize search feature.
sifter has an config option in its last version that can help you to achieve what you want, the config option is respect_word_boundaries:
If true, matches only at start of word boundaries (e.g. the beginning of words, instead of matching the middle of words)
The problem is selectize doesn't not use the latest version, so you have to use the not all-in-all bundled version of selectize called "default".
Make sure you're using sifter version 0.6.0.
I tried to do some tweaks using plugins on selectize to get this working. Check the result below:
Selectize.define('change_search', function(options) {
var self = this;
this.getSearchOptions = (function() {
var original = self.getSearchOptions();
return function() {
original['respect_word_boundaries'] = true;
return original;
};
})();
});
$(document).ready(function() {
$('#search').selectize({
plugins: ['change_search']
});
});
.search {
width: 300px;
margin: 10px;
display: block;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.6/css/selectize.default.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/microplugin/0.0.3/microplugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sifter/0.6.0/sifter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.6/js/selectize.min.js"></script>
<div class='search'>
<select placeholder="Choose one option..." id="search" multiple="multiple">
<option value="asset">Asset</option>
<option value="etc">Etcetera</option>
<option value="etymology">Etymology</option>
<option value="yet">Yet</option>
</select>
</div>
I have a problem with style sanitization with Angular 8.
I've used ngStyle multiple times, but this time i cannot set the border of a td element.
I am trying to set the border style based on a field. If this field has a relevant content for me then i hilghlight it, otherwise i don't. I don't know the number of possible values of the field, neither the exact values: it's complitely dynamic, I only know my values of interest.
I'm returning the border style from a function inside the .ts file. Here are the code snippets:
<ng-container matColumnDef="{{cam}}">
<th mat-header-cell *matHeaderCellDef class="header"> {{cam}} </th>
<td mat-cell *matCellDef="let piano" class="cellaMagazzino" [ngStyle]=" {'border':shouldHighlight(piano[cam])}">
<div>
<!--content-->
</div>
</td>
</ng-container>
My typescript function looks like this:
shouldHighlight(element){
if (this.listaCommittenti == undefined && this.listaNumOrdine == undefined) {
let found = this.releventContentList.find(item => item.property == element.property)
let result = found != undefined ? '3px solid ' + this.myVariable["color"] : ""
return result
}
I used ngStyle calling functions other times, but in this case i get the error:
WARNING: sanitizing unsafe style value 3px solid rgb(241, 196, 15) (see http://g.co/ng/security#xss).
Is there some kind of configuration to do? is there a workaround?
Does this work for you?
Typescript:
getHighlightColor():string {
return "rgba(255,255,255,1)";
}
shouldHighlight(): boolean {
return true;
}
HTML:
<td mat-cell [style.border-color]="getHighlightColor(piano[cam])" [ngClass]="{ 'highlighted': shouldHighlight(piano[cam])}"
CSS:
.highlighted{
border-width:3px;
border-style:solid;
border-color:transparent;
}
In general, I would strongly advice against using function calls in your template as it's a real performance killer. It's much better to calculate the desired classes and add them to your data instead.
Federico's approach is a nice work around, however you could also use your orignal approach and bypass the style security via bypassSecurityTrustStyle(yourStyleString) see Trusting safe values
I'm creating a list of radio buttons which when checked should change the color of corresponding label but it seems not to work at all using css selectors.
what am i missing here?
template-
<ion-list class="addressList">
<ion-radio-group">
<ion-item *ngFor="let address of address">
<label for="ok" >
{{address.address}}
</label>
<ion-radio id="ok" class="radio-custom" mode='ios' slot="end" value="{{address.address}}"></ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
app.scss -
:checked + label {
color: var(--ion-color-primary) !important;
}
I think the best way to figure out styling is to use chrome dev tools, click on the item in question and see what classes such element obtains during "checked" state:
Then you could build your styling rules around it, but please note that if the element is inside of a "shadow root" you need to use css variables to apply styles (since those elements' style would be incapsulated inside shadow dom)
<ion-list class="addressList">
<ion-radio-group>
<ion-item *ngFor="let address of [0,1,2,3,4,5,6,7]">
<ion-label>address #{{ address }}</ion-label>
<ion-radio mode='ios' slot="end" value="{{address}}"></ion-radio>
</ion-item>
</ion-radio-group>
</ion-list>
and css:
.item-radio-checked {
color: red;
}
You can play with many CSS vars Ionic team created from here: https://ionicframework.com/docs/api/item#css-custom-properties
These are applied at ion-item scope.
Right now, I'm trying to make a website that shows recent news posts which is supplied my NodeJS API.
I've tried the following:
HTML
<div id="news" class="media" v-for="item in posts">
<div>
<h4 class="media-heading">{{item.title}}</h4>
<p>{{item.msg}}</p>
</div>
</div>
JavaScript
const news = new Vue({
el: '#news',
data: {
posts: [
{title: 'My First News post', msg: 'This is your fist news!'},
{title: 'Cakes are great food', msg: 'Yummy Yummy Yummy'},
{title: 'How to learnVueJS', msg: 'Start Learning!'},
]
}
})
Apparently, the above didn't work because Vue can't render multiple root elements.
I've looked up the VueJS's official manual and couldn't come up with a solution.
After googling a while, I've understood that it was impossible to render multiple root element, however, I yet to have been able to come up with a solution.
The simplest way I've found of adding multiple root elements is to add a single <div> wrapper element and make it disappear with some CSS magic for the purposes of rendering.
For this we can use the "display: contents" CSS property. The effect is that it makes the container disappear, making the child elements children of the element the next level up in the DOM.
Therefore, in your Vue component template you can have something like this:
<template>
<div style="display: contents"> <!-- my wrapper div is rendered invisible -->
<tr>...</tr>
<tr>...</tr>
<tr>...</tr>
</div>
</template>
I can now use my component without the browser messing up formatting because the wrapping <div> root element will be ignored by the browser for display purposes:
<table>
<my-component></my-component> <!-- the wrapping div will be ignored -->
</table>
Note however, that although this should work in most browsers, you may want to check here to make sure it can handle your target browser.
You can have multiple root elements (or components) using render functions
A simple example is having a component which renders multiple <li> elements:
<template>
<li>Item</li>
<li>Item2</li>
... etc
</template>
However the above will throw an error. To solve this error the above template can be converted to:
export default {
functional: true,
render(createElement) {
return [
createElement('li', 'Item'),
createElement('li', 'Item2'),
]
}
}
But again as you probably noticed this can get very tedious if for example you want to display 50 li items. So, eventually, to dynamically display elements you can do:
export default {
functional: true,
props: ['listItems'], //this is an array of `<li>` names (e.g. ['Item', 'Item2'])
render(createElement, { props }) {
return props.listItems.map(name => {
return createElement('li', name)
})
}
}
INFO in those examples i have used the property functional: true but it is not required of course to use "render functions". Please consider learning more about functional componentshere
Define a custom directive:
Vue.directive('fragments', {
inserted: function(el) {
const children = Array.from(el.children)
const parent = el.parentElement
children.forEach((item) => { parent.appendChild(item) })
parent.removeChild(el)
}
});
then you can use it in root element of a component
<div v-fragments>
<tr v-for="post in posts">...</tr>
</div>
The root element will not be rendered in DOM, which is especially effective when rendering table.
Vue requires that there be a single root node. However, try changing your html to this:
<div id="news" >
<div class="media" v-for="item in posts">
<h4 class="media-heading">{{item.title}}</h4>
<p>{{item.msg}}</p>
</div>
</div>
This change allows for a single root node id="news" and yet still allows for rendering the lists of recent posts.
In Vue 3, this is supported as you were trying:
In 3.x, components now can have multiple root nodes! However, this does require developers to explicitly define where attributes should be distributed.
<!-- Layout.vue -->
<template>
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
</template>
Multiple root elements are not supported by Vue (which caused by your v-for directive, beacause it may render more than 1 elements). And is also very simple to solve, just wrap your HTML into another Element will do.
For example:
<div id="app">
<!-- your HTML code -->
</div>
and the js:
var app = new Vue({
el: '#app', // it must be a single root!
// ...
})
I am trying to create a one page website that is similar this example :
http://themeforest.net/theme_previews/6622929-glissando-creative-minimal-onepage-psd-template?index=1&url_name=glissando-creative-minimal-onepage-psd-template
I thought I could use the transform css property but It's not giving me exactly what I want. Does anyone have any insight into this? I'm really new to coding!
Thanks!
html:
<div class="about">
<div class="aboutcontent">
</div>
</div>
scss:
.about {
width: 100%;
background: white;
transform: skewY(-5deg);
padding: 150px;
.aboutcontent {
transform: skewY(5deg);
}
}
I figured out the answer! My above code was actually correct. To make my website look like the example you should put a background image on the body and then you can position the skewY divs appropriately!