DropDown popup width (Telerik: Kendo UI for Angular) - kendo-ui-angular2

How can I set DropDown popup width to auto, so all text is visible? I would like to keep small width for widget, but larger width for popup.
Updated:
Link to Plunkr.
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
styles: ['kendo-dropdownlist { width: 6em;}'],
template: `
<kendo-dropdownlist
[data]="listItems"
[textField]="'text'"
[valueField]="'value'"
[value]="selectedValue"
>
<ng-template kendoDropDownListValueTemplate let-dataItem>
<span>{{ dataItem?.value }}</span> {{ dataItem?.text }}
</ng-template>
<ng-template kendoDropDownListItemTemplate let-dataItem>
<span>{{ dataItem.value }}</span> {{ dataItem.text }} - Dummy text
</ng-template>
</kendo-dropdownlist>
`
})
export class AppComponent {
public listItems: Array<{ text: string, value: number }> = [
{ text: "Small", value: 1 },
{ text: "Medium", value: 2 },
{ text: "Large", value: 3 }
];
public selectedValue: { text: string, value: number } = { text: "Foo", value: 1 };
}

I would suggest you to set the popup width to auto. Thus the items will not wrap:
<kendo-dropdownlist
[data]="listItems"
[textField]="'text'"
[valueField]="'value'"
[value]="selectedValue"
[popupSettings]="{ width: 'auto' }"
>
http://plnkr.co/edit/dqlInPutekCnwdt7KFek?p=preview

Related

Adding Stripe Subscription to Blazor WASM

I am trying to add Stripe Subscription to my Blazor WASM Application following these instructions Since they are using JavaScript I am using the JavaScript interop. I added Stripe's script to my index.html and added a custom script with the javascript they have in the instructions.
Index.html inside the <head> tag
<script src="https://js.stripe.com/v3/"></script>
<script src="stripescript.js"></script>
stripescript.js:
let stripe = window.Stripe('MY PUBLIC KEY');
let elements = stripe.elements();
let card = elements.create('card', { style: style });
card.mount('#card-element');
card.on('change', function (event) {
displayError(event);
});
function displayError(event) {
changeLoadingStatePrices(false);
let displayError = document.getElementById('card-element-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
}
function createPaymentMethod(cardElement, customerId, priceId) {
return stripe
.createPaymentMethod({
type: 'card',
card: cardElement,
})
.then((result) => {
if (result.error) {
displayError(error);
} else {
//change this to call .net
createSubscription({
customerId: customerId,
paymentMethodId: result.paymentMethod.id,
priceId: priceId,
});
}
});
}
My assumption is that the variable initializations would happen when the application is loaded. However, when I add the following HTML to my Razor page is not populating the card component.
<form id="payment-form">
<div id="card-element">
<!-- Elements will create input elements here -->
</div>
<!-- We'll put the error messages in this element -->
<div id="card-element-errors" role="alert"></div>
<button type="submit">Subscribe</button>
</form>
I am lost on how to debug this, or if this is even possible in Blazor.
Thanks to #Umair's Comments, I realized that I had made a few mistakes and some of them were showing up in the console since I was trying to initialize the card element before the DOM was loaded. I was able to fix my problem by first changing the card mount into its own function. Here is the full stripescript.js for future people that have this problem:
let stripe = window.Stripe('MY KEY');
let elements = stripe.elements();
let style = {
base: {
fontSize: '16px',
color: '#32325d',
fontFamily:
'-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif',
fontSmoothing: 'antialiased',
'::placeholder': {
color: '#a0aec0',
},
},
};
let card = elements.create('card', { style: style });
function mountCard() {
card.mount('#card-element');
}
card.on('change', function (event) {
displayError(event);
});
function displayError(event) {
changeLoadingStatePrices(false);
let displayError = document.getElementById('card-element-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
}
function createPaymentMethod(cardElement, customerId, priceId) {
return stripe
.createPaymentMethod({
type: 'card',
card: cardElement,
})
.then((result) => {
if (result.error) {
displayError(error);
} else {
//todo change this to call .net
createSubscription({
customerId: customerId,
paymentMethodId: result.paymentMethod.id,
priceId: priceId,
});
}
});
}
and added the following C# code to my Blazor component to render the card:
[Inject] IJSRuntime js { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await js.InvokeVoidAsync("mountCard");
}
I found a solution for this on Youtube that is super complicated, and I decided to create my own implementation following KISS.
I have streamlined youtube's implementation on a single StripeCard component that interacts with my custom Js StripeInterop. I hope this makes your life easier.
This will allow you to have different publishable keys for your different environments without hardcoding it and reuse the component in multiple pages if you wish. Also, it will destroy itself when the component is used.
Here is my solution for (blazor webassembly).
Add this to index.html
<!-- Stripe -->
<script src="https://js.stripe.com/v3/"></script>
<script src="stripescript.js"></script>
Here is stripescript.js
StripeInterop = (() => {
var stripe = null;
var elements = null;
var dotNetReference = null;
var card = null;
var style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
return {
init(dotnetHelper, publishableKey) {
stripe = window.Stripe(publishableKey);
elements = stripe.elements();
card = elements.create('card', { style: style });
dotNetReference = dotnetHelper;
card.mount('#card-element');
card.on('change', function (event) {
displayError(event);
});
},
createPaymentMethod(billingEmail, billingName) {
return stripe
.createPaymentMethod({
type: 'card',
card: card,
billing_details: {
name: billingName,
email: billingEmail
}
})
.then(function (result) {
if (result.error) {
displayError(result);
} else {
dotNetReference.invokeMethodAsync('ProcessPaymentMethod', result.paymentMethod.id);
}
});
},
destroy() {
dotNetReference.dispose();
card.destroy();
}
};
function displayError(event) {
var showError = document.getElementById('card-element-errors');
if (event.error) {
showError.textContent = event.error.message;
} else {
showError.textContent = '';
}
}
})();
Here is StripeCard.razor component
#namespace SmartApp.Components
<div id="card-element" style="display: block;
width: 100%;
padding: 0.52rem .75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: .25rem;
transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;">
</div>
<div id="card-element-errors" class="validation-message"></div>
Here is StripeCard.razor.cs
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace SmartApp.Components
{
public partial class StripeCard : IDisposable
{
[Inject] IJSRuntime JS { get; set; }
[Parameter] public string PublishableKey { get; set; }
[Parameter] public EventCallback<string> CardProcessedCallBack { get; set; }
private bool _firstTime;
protected override async Task OnInitializedAsync()
{
_firstTime = true;
await base.OnInitializedAsync();
}
public async void Dispose()
{
await JS.InvokeVoidAsync("StripeInterop.destroy");
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (_firstTime)
{
_firstTime = false;
await JS.InvokeVoidAsync("StripeInterop.init", DotNetObjectReference.Create(this), PublishableKey);
}
}
[JSInvokable("ProcessPaymentMethod")]
public Task ProcessPaymentMethod(string paymentId)
{
return CardProcessedCallBack.InvokeAsync(paymentId);
}
}
}
Here is how we use StripeCard.razor in our Page.
#page "/subscription/payment"
#attribute [Authorize(Roles = "Admin,Organisation")]
#inject IJSRuntime JS
<div class="card card-custom card-shadowless rounded-top-0">
<div class="card-body p-0">
<div class="row justify-content-center py-8 px-8 py-lg-15 px-lg-10">
<div class="col-xl-12 col-xxl-7">
<!--begin: Wizard Form-->
<EditForm Model="#_model" OnValidSubmit="HandleValidSubmit" >
<DataAnnotationsValidator />
<h4 class="mb-10 font-weight-bold text-dark">Enter your Payment Details</h4>
<div class="row">
<div class="col-xl-6">
<!--begin::Input-->
<div class="form-group">
<label>Name on Card</label>
<InputText #bind-Value="_model.BillingName" name="ccname" class="form-control form-control-solid form-control-lg"
placeholder="Jane Doe" />
<ValidationMessage For="#(() => _model.BillingName)" />
</div>
<!--end::Input-->
</div>
<div class="col-xl-6">
<!--begin::Input-->
<div class="form-group">
<label>Notification Email</label>
<InputText #bind-Value="_model.BillingEmail" name="ccemail" class="form-control form-control-solid form-control-lg"
placeholder="jane.doe#domain.com" />
<ValidationMessage For="#(() => _model.BillingEmail)" />
</div>
<!--end::Input-->
</div>
</div>
<div class="row">
<div class="col-xl-12">
<!--begin::Input-->
<div class="form-group">
<label>Card Information</label>
<StripeCard PublishableKey="#_stripePublishableKey" CardProcessedCallBack="ProcessSubscriptionAsync"></StripeCard>
<span class="form-text text-muted">Powered by <strong>Stripe</strong>.</span>
</div>
<!--end::Input-->
</div>
</div>
<ValidationSummary />
<div class="d-flex justify-content-between border-top mt-5 pt-10">
<div>
<button type="button" class="btn btn-success font-weight-bolder text-uppercase px-9 py-4"
#onclick="HandleValidSubmit">
Submit
</button>
</div>
</div>
</EditForm>
<!--end: Wizard Form-->
</div>
</div>
</div>
</div>
#code{
private Model _model;
private string _stripePublishableKey;
protected override void OnInitialized()
{
_model = new Model();
_stripePublishableKey = "Here we put Development or Production publishableKey"; //Add publishable key here
base.OnInitialized();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JS.InvokeVoidAsync("KTSubscriptionCheckout.init");
}
await base.OnAfterRenderAsync(firstRender);
}
private async Task HandleValidSubmit()
{
await JS.InvokeVoidAsync("StripeInterop.createPaymentMethod", _model.BillingEmail, _model.BillingName);
}
//Callback method will return stripe paymentId
private async Task ProcessSubscriptionAsync(string paymentId)
{
//We process paymentId here and continue with our backend process
await Task.CompletedTask;
}
public class Model
{
[Required]
public string BillingName { get; set; }
[Required]
public string BillingEmail { get; set; }
}
}
Youtube video if you want to have a look. https://youtu.be/ANYvFHHfyy8
Good luck...

ZingChart Y Axis Label Formatting

Is it possible in ZingChart to add a secondary y scale that uses the same values as the primary y scale, but just uses a simple conversion (e.g., anomaly degrees Celsius*1.8 = anomaly degrees Fahrenheit).
something like:
var chartConfig = {
scaleY2: { format: %v*1.8 }
}
Or, perhaps a function, like:
var chartConfig = {
scaleY2: { format: 'formatAxis()' }
}
...
formatAxis = function(p){ return { format:p.value*1.8 } }
I'm plotting temperature anomalies in degrees C on the primary y-axis. I'd like the degrees F to show up on the secondary y-axis.
You do indeed use a function. I just had a syntax error.
var chartConfig = {
scaleY2: { format: 'formatAxis()' }
}
...
window.formatAxis = function(v){
return (v*1.8).toFixed(2)+'\u00B0F';
}
The above answer from #magnum-π is correct. Creating a formatting function is the easiest and most effective solution.
// how to call function from ZingChart
let chartConfig = {
scaleY2: { format: 'formatAxis()' }
}
// defining function for ZingChart to find at the window scope
window.formatAxis = function(v){
return (v*1.8).toFixed(2)+'\u00B0F';
}
I have also configured a working demo of this to assist the above answer:
// window.onload event for Javascript to run after HTML
// because this Javascript is injected into the document head
window.addEventListener('load', () => {
// Javascript code to execute after DOM content
// full ZingChart schema can be found here:
// https://www.zingchart.com/docs/api/json-configuration/
let chartConfig = {
type: 'bar',
globals: {
fontSize: '14px',
},
title: {
text: 'Multiple Scales °C vs °F',
fontSize: '24px',
adjustLayout: true,
},
legend: {
draggable: true,
},
// plot represents general series, or plots, styling
plot: {
// hoverstate
tooltip: {
// % symbol represents a token to insert a value. Full list here:
// https://www.zingchart.com/docs/tutorials/chart-elements/zingchart-tokens/
text: '%kl was %v° %plot-text',
borderRadius: '3px',
// htmlMode renders text attribute as html so
// ° is rendered
htmlMode: true
},
valueBox: {
color: '#fff',
placement: 'top-in'
},
// animation docs here:
// https://www.zingchart.com/docs/tutorials/design-and-styling/chart-animation/#animation__effect
animation: {
effect: 'ANIMATION_EXPAND_BOTTOM',
method: 'ANIMATION_STRONG_EASE_OUT',
sequence: 'ANIMATION_BY_NODE',
speed: 275
}
},
plotarea: { margin: 'dynamic',},
scaleX: {
// set scale label
label: {
text: 'Days'
},
// convert text on scale indices
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
scaleY: {
// scale label with unicode character
label: {
text: 'Temperature (°C)'
}
},
scaleY2: {
label: {
text: 'Temperature (°F)'
},
guide: { visible: false }
},
// plot values
series: [
{
text: 'Celcius',
values: [23, 20, 27, 29, 25, 17, 15],
backgroundColor: '#448aff #64b5f6' ,
scales: 'scale-x, scale-y'
},
{
text: 'Farenheit',
values: [35, 42, 33, 49, 35, 47, 35].map(v => Number((v*1.8).toFixed(2))),
backgroundColor: '#ff5252 #e57373',
scales: 'scale-x, scale-y-2'
}
]
};
// render chart
zingchart.render({
id: 'myChart',
data: chartConfig,
height: '100%',
width: '100%',
});
});
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.chart--container {
min-height: 150px;
width: 100%;
height: 100%;
}
.zc-ref {
display: none;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ZingSoft Demo</title>
<script src="https://cdn.zingchart.com/zingchart.min.js"></script>
</head>
<body>
<!-- CHART CONTAINER -->
<div id="myChart" class="chart--container">
<a class="zc-ref" href="https://www.zingchart.com/">Powered by ZingChart</a>
</div>
</body>
</html>

react-virtualized: Table Column with CellMeasurer always has cache height

I've been trying to follow the DynamicHeightTableColumn example and adapt it for my use case. I can see in the CellMeasurer demo that the single-line rows have the default height, defined when initializing the cache. However, in my case, it seems like single-line rows always have the tallest row height, stored in the cache, instead of the default one.
Here is my code:
import * as React from 'react';
import * as Immutable from 'immutable';
import { Table, Column, AutoSizer, CellMeasurer, CellMeasurerCache } from 'react-virtualized';
interface Props {
logs: Immutable.List<Immutable.Map<string, any>>;
columns: (
width: number
) => Array<{
name: string;
key: string;
width: number;
variableHeight?: boolean;
}>;
}
export default class LogTable extends React.Component<Props, {}> {
private cache: CellMeasurerCache;
constructor(props) {
super(props);
this.cache = new CellMeasurerCache({
defaultHeight: 20,
fixedWidth: true,
keyMapper: () => 1
});
}
render() {
const { logs } = this.props;
return (
<AutoSizer disableHeight>
{({ width }) => (
<Table
headerHeight={20}
height={250}
rowCount={logs.size}
rowHeight={this.cache.rowHeight}
width={width}
overscanRowCount={2}
rowRenderer={this.rowRenderer}
headerClassName='col-header'
gridClassName='log-table-grid'
rowClassName='log-table-row'
className='log-table'
rowGetter={({ index }) => logs.get(index)}
deferredMeasurementCache={this.cache}>
{this.renderColumns(width)}
</Table>
)}
</AutoSizer>
);
}
private renderColumns(width) {
return this.props.columns(width).map(({ name, key, width, variableHeight }, idx) => {
const props: any = {
label: name,
dataKey: key,
width,
key,
className: 'column'
};
if (variableHeight) {
props.cellRenderer = this.cellRenderer.bind(this, idx);
}
return <Column {...props} />;
});
}
private rowRenderer(params) {
const { key, className, columns, rowData, style } = params;
if (!rowData) {
return null;
}
return (
<div className={className} key={key} style={style}>
{columns}
</div>
);
}
private cellRenderer(colIndex, { dataKey, parent, rowIndex }) {
const content = this.props.logs.get(rowIndex).get(dataKey);
return (
<CellMeasurer
cache={this.cache}
columnIndex={colIndex}
key={dataKey}
parent={parent}
rowIndex={rowIndex}>
<div style={{ whiteSpace: 'normal' }} title={content}>
{content}
</div>
</CellMeasurer>
);
}
}
And this is the output (see 2nd row in the table that's too tall for its content)
The only styling (less) I have is the following, which I don't think can cause this behavior
.log-table {
font-size: 14px;
.col-header {
font-size: 15px;
text-align: center;
}
.log-table-grid {
outline: none;
font-family: monospace;
}
.log-table-row {
border-bottom: 1px solid gray;
padding: 3px;
}
}

How can I create an SVG Icon from an SVG image with material ui?

So, I'm trying to create a custom Svgicon, but all the source code uses the paths directly. Is there anyway I can add an SVG icon from an image like this?
import { SvgIcon } from '#material-ui/core';
import React from 'react';
const iconStyles = {
marginRight: 24,
};
export const LawyersIcon = props => (
<SvgIcon {...props}>
<img src="https://pictures-for-website.nyc3.digitaloceanspaces.com/icons/team.svg" />
</SvgIcon>
);
So, you actually don't need to use SvgIcon at all, you can just create your own icon. This is my final code:
import { withStyles } from '#material-ui/core';
import React from 'react';
#withStyles(theme => ({
svg_icon: {
width: '1em',
height: '1em',
display: 'inline-block',
fontSize: '24px',
transition: 'fill 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
flexShrink: 0,
userSelect: 'none',
}
}))
export class LawyersIcon extends React.Component {
render() {
const { classes } = this.props
return <div className={classes.svg_icon}>
<img src="https://pictures-for-website.nyc3.digitaloceanspaces.com/icons/team.svg" />
</div>
}
}

AUI datepicker: pop up datepicker on focus of element

How can i make AUI-datepicker to pop up on the focus of element. cuurrently it only pop up on click of element.
Here is code
Script:
YUI().use('aui-datepicker',
function(Y) {
new Y.DatePicker(
{
trigger: '.date-selector',
popover: {
zIndex: 1
},
}
);
}
);
and Tag
<aui:input id="startDate" name="startDate" cssClass="date-selector" label="startDate">
and one more thing how can i range date?
Try this something like this:
<aui:input name="taskStartDate" autocomplete="off" cssClass='font-size' id="taskStartDate" onFocus="onClickOfStartDate();" required="true" inlineLabel="true" label=" "/>
<aui:script>
function setactualStartDate(){
AUI().use('aui-datepicker', function(A) {
var simpleDatepicker1 = new A.DatePicker({
trigger: '#<portlet:namespace />taskActualStartDate',
mask: '%Y-%m-%d',
calendar: {
dateFormat: '%Y-%m-%d',
},
}).render('#<portlet:namespace />taskactualStartDatePicker');
});
}
function onClickOfStartDate(){
setStartDate();
}
</aui:script>
The Datepicker popup is handled by DatePickerPopover class of aui-datepicker module. There is show() method in datepicker class to open popup.
<input id="startDate" name="startDate" class="date-selector" onfocus="openDatePicker();">
<script>
var datePicker;
YUI().use('aui-base','aui-datepicker', function(Y) {
datePicker = new Y.DatePicker({
trigger: '#startDate',
popover: {
zIndex: 10,
},
calendar: {
maximumDate: new Date()
}
});
});
function openDatePicker() {
datePicker.getPopover().show();
}
</script>
Date can be ranged by adding maximumDate and minimumDate attribute.

Resources