How to customise the way a CheckboxSelectMultiple widget renders via crispyforms? - checkbox

I have a Django ModelForm that renders a ForeignKey field using the CheckboxSelectMultiple widget. I want to be able to change the display of the checkboxes by adding and/or removing some css classes.
In the template, the form renders as follows:
<div id="id_activities" class="form-group">
<label class="" for"">Choose Activities:</label>
<div class="">
<div class="custom-control custom-checkbox">
<input id="id_activities_1" class="custom-control-input" type="checkbox" name="activities" value="1"/>
<label class="custom-control-label" for="id_activities_1">..</label>
</div>
</div>
</div>
I would like to be able to customise the look of the checkboxes with some non-bootstrap classes. I've tried providing a template with the following html:
{% load crispy_forms_field %}
<div class="form-group">
<label class="" for="">Choose Activities</label>
<div>
<div class="custom-control custom-checkbox addon">
{% crispy_field field 'class' 'custom-control-input' %}
<label class="custom-control-label small" for="{{ field.id_for_label }}">{{ field.label }}</label>
</div>
</div>
</div>
But that causes the input to be wrapped in a <ul>
I am currently trying to override the bootstrap classes in my own scss file but feel dissatisfied with this workaround as I would like a bit more control. Is there an better way of customising the CheckboxSelectMultiple? Would I need to go as far as creating a custom Layout object?

To solve this I subclassed the CheckboxSelectMultiple widget and provided my own templates for tempate_name and option_template_name. I largely reused the django template code but exchanged the list elements for divs

Related

Nested directives with transclusion

I have a set of form directives in which duplicate code can be extracted into a separate directive.
I know that I can use transclusion, but have not been able to identify any technique that allows this (element cloning or passing functions). Tutorials on pluralsight, sitepoint and few other describe extraction into a directive inside the current directive, but I have not been able to apply them to my use case.
Brief Synopsis:-
Two sample directives
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 col-xl-2">
<div class="form-group">
<label ng-show="visible">Input:
<input ng-model="person.name" type="text" required>
</label>
<p ng-show="!visible"> {{person.name}} </p>
</div>
</div>
And
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 col-xl-2">
<div class="form-group">
<label ng-show="visible">Input:
<select> <option value="volvo">Volvo</option> .... </select>
</label>
<p ng-show="!visible"> {{person.name}} </p>
</div>
</div>
I wish to condense them into directives like
<my-input-box ng-model="person.name" required></my-input-box>
<my-select-box options = "person.options"></my-select-box>
where my-input-box template is
<my-wrapper-box><input ng-model="person.name" type="text" required></my-wrapper-box>
and my-select-box template is
<my-wrapper-box><select>......</select></my-wrapper-box>
Please see this plunker: http://plnkr.co/edit/k6LWjn?p=preview
How do I extract the wrapper box so that 2-way binding is maintained with the ng-model and overriding attributes like required, bootstrap classes, validation regex, etc. in either the my-wrapper-box or the transcluded HTML element?
Many thanks to all who have read the question. I look forward to your suggestions.
Plunker.
I've added the following to myInputBox directive:
controller: function(){},
bindToController: true,
controllerAs: 'ctrl',
and changed the html to
<my-wrapper-box>
<input type="text" ng-required="reqd" ng-model="ctrl.value" />
</my-wrapper-box>

How can I have two ng-contents in the same template controlled by *ngIf

I have an angular 2 component for displaying a bootstrap 3 button group. The component can either have a label or it can stand alone.
My solution was to use two ng-contents controlled by an *ngIf however, it refuses to display either of the ng-contents and does not throw an error.
Here's btn-multi.html:
<div class="form-group"
*ngIf="label">
<label class="control-label col-lg-2 col-md-3">
{{ label }}
</label>
<div class="col-lg-10 col-md-9">
<div class="btn-group">
<ng-content></ng-content>
</div>
</div>
</div>
<div class="btn-group"
*ngIf="!label">
<ng-content></ng-content>
</div>
And here is how it is used:
<btn-multi label="Some Label"
[(value)]="someValue">
<btn [value]="true">Yes</btn>
<btn [value]="false">No</btn>
</btn-multi>
And this is it working with just the one ng-content:
I'm currently on angular 2 beta-15.
Thanks!
NgIf is getting in the way of including the content since ng-content is being rendered after NgIf is evaluated.
You need to take another approach on it, maybe something like this:
<div [ngClass]="{'form-group': label}">
<label *ngIf="label" class="control-label col-lg-2 col-md-3">
{{ label }}
</label>
<div [ngClass]="{'col-lg-10 col-md-9': label}">
<div class="btn-group">
<ng-content></ng-content>
</div>
</div>
</div>
And there are also even better ways to do it, it all depends on how you want this component to be consumed.
FYI, just did this on the fly so its not tested, but just to give you a general idea.

Horizontal Fields

Looking at this example: http://angular-formly.com/#/example/bootstrap-specific/advanced-layout
What makes the fields display horizontally? Is it the row class on the field group? Or at the col-xs-6 classes on the individual fields (when looking just at the First/Last name fields)?
I am asking because at my work we are unable to use the twitter bootstrap (arg!) and I am having trouble making fields get on the same lines like this example when not using the bootstrap.
Do you have to use the bootstrap classes in order to get fields on the same row?
CSS. They are wrapped in a div with the col-xs-6 class applied. That class is floated left and has a width of 50%.
.col-xs-6 {
width:50%;
float:left;
}
https://jsfiddle.net/6njkou1g/
Depending on the browser support you need, you might consider this example which doesn't require bootstrap at all and instead uses flexbox to do layout. Otherwise, what Brian said about implementing a subset of bootstrap's grid system yourself wouldn't be too tricky...
Use col-xs-6 for two columns.
<form class="form">
<div class="row">
<div class="col-xs-6">
<div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email">
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
</div>
</div>
</div>
</form>
http://jsfiddle.net/rwfje779/

ngif markup error while displaying ngMessages error in angularjs

i am using ngMessages to validate a form , which is dynamically generated using ngRepeat.ngMessages is working fine but i want to display validation error messages only submit button is clicked.I am using ng-if for checking
submit button clicked and current form field is invalid . but i am getting angular compiler error , i think it is something to do with constructing the control name dynamically.
can any one suggest what is wrong with following markup.
<div ng-repeat="item in Data" class="container-fluid">
<ng-form name="fm">
<div class="row">
<div class="col-md-10">
<h2>{{ item.headerName}}</h2>
</div>
</div>
<div class="row" ng-repeat="it in item.items">
<div class="col-md-8">
<div class="form-group">
<label for="''{{ it.name}}''" class="col-xs-4 control-label"> {{ it.name}}</label>
<div class="col-xs-2">
<select name='{{"yOrNo" + $parent.$index + $index}}'
id='{{"yOrNo" + $parent.$index + $index}}'
class="form-control"
data-ng-disabled="false"
ng-model="it.yesorNo"
ng-options="yno.id as yno.value for yno in lookups.yno"
ng-required="true"></select>
<div class="messages" ng-messages="fm.yOrNo{{$parent.$index}}{{$index}}.$error" ng-if="fm.yOrNo{{$parent.$index}}{{$index}}.$error && submitClicked" >
<div class="error-message" ng-message="required">* required.</div>
</div>
</div>
</div>
</div>
</div>
</ng-form>
</div>
Your ng-form needs a unique name per iteration, so instead of:
<ng-form name="fm"> try something like:
<ng-form name="fm{{$index}}">
note that all references to that name=fm{{$index}} will now needs to be adjusted accordingly, E.G: this: fm.yOrNo{{$parent.$index}}{{$index}}.$error will need to become this: fm{{$parent.$index}}.yOrNo{{$parent.$index}}{{$index}}.$error

How to style inside an AngularJS modal form?

I have an AngularJS Modal Bootstrap form working. How do I style the text inside the form? In the example below, I'd like 'Name' to be Bold. I've tried label, divs, ng-class but that seems to get stripped out when Angular processes the form.
<form novalidate class="simple-form">
<div ng-class="col-sm-2 control-label">Code:</div> {{Code}}
<label>Name:</label> {{Name}}
<label>Our Name:</label><input type="text" ng-model="Our_Name" />
</form>
When I view the source it always comes out:
<form novalidate="" class="simple-form ng-scope ng-pristine ng-valid ng-binding">
Code: C11 Name: Accredited Surety Cas Co.
Our Name: <input type="text" ng-model="Our_Name" class="ng-pristine ng-valid"><br>
</form>
Thanks for looking.
I hope you have included bootstrap.css in your code. And for modal window you need to add modal specific classes like below.
<form novalidate>
<div class="modal-dialog simple-form">
<div class="modal-content">
<div class="modal-header">
//your rest html
</div>
</div>
</div>
</form>
Here is an updated fiddle.
I hope this is what you are looking for.
Thanks

Resources