Card Sizing Issue(s) ... Multiple Cards on a Page
There are times I have multiple credit card inputs as you'll see in the screenshot(s) below. I don't think it's pertinent based on how I'm using card, but this is in an Angular app. I initialize the card as follows...
const cardContainer = '.card-container-'+this.roomIndex;
const ccNumber = 'input#td-cc-number-'+this.roomIndex;
const ccName = 'input#td-cc-first-name-'+this.roomIndex+', input#td-cc-last-name-'+this.roomIndex;
const ccExpiry = 'input#td-cc-expiry-'+this.roomIndex;
const ccCvc = 'input#td-cc-cvc-'+this.roomIndex;
// Initialize Card
$(this.element.nativeElement).card({
// a selector or DOM element for the container
// where you want the card to appear
container: cardContainer, // *required*
width: 250,
formSelectors: {
numberInput: ccNumber, // optional — default input[name="number"]
nameInput: ccName,
expiryInput: ccExpiry, // optional — default input[name="expiry"]
cvcInput: ccCvc // optional — default input[name="cvc"]
},
formatting: true, // optional - default true
// Strings for translation - optional
messages: {
validDate: 'valid\ndate', // optional - default 'valid\nthru'
monthYear: 'mm-yyyy' // optional - default 'month/year'
},
// Default placeholders for rendered fields - optional
placeholders: {
number: '•••• •••• •••• ••••',
name: 'Full Name',
expiry: '••-••••',
cvc: '•••'
},
// if true, will log helpful messages for setting up Card
debug: true // optional - default false
});
As you can see there, I have specified the width. This works for the first card in the loop of initializations... Below is the screenshot showing the first one and another one with varying size.

I started trying to specify the size of the card when the cards were not appropriately re-sizing as they do on the demo page. So I could be doing something wrong. I'll show my relevant template code for completeness...
<div class="col-sm-6" *ngFor="let traveler of hotelReservation?.travelers; let i = index; let isFirst = first">
<div class="panel panel-primary">
<div class="pull-right text-primary m-r-10 m-t-5" *ngIf="isFirst">Primary</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
<div>
<span class="room-title">Room {{ i + 1 }}</span>
<div *ngIf="isFirst || !traveler.sameName">
<input name="firstName" type="text" placeholder="First" [(ngModel)]="traveler.firstName" required>
<input name="lastName" type="text" placeholder="Last" [(ngModel)]="traveler.lastName" required>
<input name="loyalty" type="text" placeholder="Loyalty" [(ngModel)]="traveler.loyalty">
</div>
</div>
<div class="row" *ngIf="isFirst || !traveler.samePayment">
<div id="form-{{i}}" piCreditCard [roomIndex]="i">
<div class="well m-t-15" id="td-card-details-{{i}}">
<div class="well-title">Payment Details</div>
<div class="row">
<div class="col-sm-6">
<input [(ngModel)]="traveler.creditCard.firstName" type="text" required class="form-control" id="td-cc-first-name-{{i}}" placeholder="First Name" name="cc-first-name" autocomplete="cc-given-name">
</div>
<div class="col-sm-6">
<input [(ngModel)]="traveler.creditCard.lastName" type="text" required class="form-control" id="td-cc-last-name-{{i}}" placeholder="Last Name" name="cc-last-name" autocomplete="cc-family-name">
</div>
</div>
<div class="row">
<div class="col-sm-6">
<input [(ngModel)]="traveler.phone" type="tel" alt="Phone Number" required class="form-control" placeholder="Phone" name="phoneNumber" id="td-phoneNumber-{{i}}" autocomplete="tel">
</div>
<div class="col-sm-6">
<input [(ngModel)]="traveler.email" type="email" alt="Email Address" required class="form-control" placeholder="Email" name="email" id="td-email-{{i}}" autocomplete="email">
</div>
</div>
<div class="row m-b-10 m-t-10">
<div class="col-sm-12">
<div class="card-container-{{i}}"></div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<input [(ngModel)]="traveler.creditCard.ccNumber" type="tel" required class="form-control" id="td-cc-number-{{i}}" placeholder="Card Number" name="cc-number" autocomplete="cc-number">
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-8">
<input [(ngModel)]="traveler.creditCard.ccExpiry" type="tel" required class="form-control" id="td-cc-expiry-{{i}}" placeholder="MM-YYYY" name="cc-expiry" autocomplete="cc-exp">
</div>
<div class="col-xs-12 col-sm-4">
<input [(ngModel)]="traveler.creditCard.ccCvc" type="tel" required class="form-control" id="td-cc-cvc-{{i}}" placeholder="CVC" name="cc-cvc" autocomplete="cc-csc">
</div>
</div>
</div>
</div>
</div>
<div *ngIf="!isFirst">
<label>
<input type="checkbox" name="sameName" [(ngModel)]="traveler.sameName"/>
Use Primary Name
</label>
<label>
<input type="checkbox" name="samePayment" [(ngModel)]="traveler.samePayment"/>
Use Primary Payment
</label>
</div>
</div>
</div>
</div>
</div>
</div>
For those not familiar with Angular, the piCreditCard directive is what actually initializes the card(s).
I have made a "stab" attempt at solving this, but I'm not a CoffeeScript person, and unfortunately I don't have the time at the moment to learn it as well as I would hope. So maybe someone can point me in the right direction, or fix this. It would be greatly appreciated.
The ultimate fix for me would also be knowing how to make it responsive. That would be much more impressive for my client as they would like it larger on the larger screens, but I must be thinking about their users more than themselves.
Thanks! Jarvis
Ah! I understand what the issue is here — it looks like you're using one selector for multiple cards. Instead, you should instantiate a new card instance for every card! Is that possible with the angular library?
@jessepollak I am initializing using the first code block for each payment on the page. So I have two issues... the primary would eliminate the need of the secondary...
- I'm unable to get my cards to be responsive. How do you do this on the demo page? (Maybe I should just update and see if this is fixed for me)
- If I cannot get the cards to be responsive, I need to specify that width which makes it look good for the majority of screens, but right now only the first instance gets the width.
Thoughts?
Thanks, Jarvis
I had the same issue and just solved by using different indexes to each card. Very ugly solution but it works... I guess somewhere in the library prevents attaching new instance to same container or form selector.
`let ccBoxes = $(".credit-card"); ccBoxes.each((index, element) => {
$(element).card({
// a selector or DOM element for the container
// where you want the card to appear
container: '.card-wrapper' + index, // *required*
formSelectors: {
nameInput: ['input[name="creditCard'+ index +'[name]"]'],
numberInput: ['input[name="creditCard'+index+'[number]"]'],
},
placeholders: {
number: '',
name: '',
expiry: '',
cvc: ''
},
masks: {
cardNumber: '•' // optional - mask card number.
},
formatting: true, // optional - default true
debug:true
});
}); `
In addition to @ keremcankaya0's answer, I also had to make the form: document.querySelector('form') unique by adding an id attribute, with an index in the id value, to for the form element, just like what is required for container.
So it looks like:
<div class="card-wrapper-1"></div>
<form id="some-id-1">
...
</form>
<div class="card-wrapper-2"></div>
<form id="some-id-2">
...
</form>
Then...
new Card({
form: document.querySelector('#some-id-' + index),
container: ('.card-wrapper-' + index),
...
})
Eu tive o mesmo problema e acabei de resolver usando índices diferentes para cada cartão. Solução muito feia, mas funciona ... Acho que em algum lugar da biblioteca impede a anexação de uma nova instância ao mesmo contêiner ou seletor de formulário.
`let ccBoxes = $(".cartão de crédito"); ccBoxes.each((índice, elemento) => {
$(element).card({ // a selector or DOM element for the container // where you want the card to appear container: '.card-wrapper' + index, // *required* formSelectors: { nameInput: ['input[name="creditCard'+ index +'[name]"]'], numberInput: ['input[name="creditCard'+index+'[number]"]'], }, placeholders: { number: '', name: '', expiry: '', cvc: '' }, masks: { cardNumber: '•' // optional - mask card number. }, formatting: true, // optional - default true debug:true });}); `
I had the same issue and just solved by using different indexes to each card. Very ugly solution but it works... I guess somewhere in the library prevents attaching new instance to same container or form selector.
`let ccBoxes = $(".credit-card"); ccBoxes.each((index, element) => {
$(element).card({ // a selector or DOM element for the container // where you want the card to appear container: '.card-wrapper' + index, // *required* formSelectors: { nameInput: ['input[name="creditCard'+ index +'[name]"]'], numberInput: ['input[name="creditCard'+index+'[number]"]'], }, placeholders: { number: '', name: '', expiry: '', cvc: '' }, masks: { cardNumber: '•' // optional - mask card number. }, formatting: true, // optional - default true debug:true });}); `
thanks bro. it's work