My company currently uses Angular Material to style inputs, buttons and etc. We're moving to a different style but Id still like to use the fancy components like Datepicker, Prefix, Suffix, and alike.
Is there a way to use material components with our own custom style?
Attached is a picture of the Datepicker vs our new style. We'd like the datepicker to take on our new style, getting rid of all the Material styling.
Here is an example of the different types of html:
//Material Input
<mat-form-field floatLabel="always" class="dynamic-input" *ngIf="answer.isInput && !answer.isConditional">
<span matPrefix *ngIf="answer.hasPrefix">{{answer.prefixText}}</span>
<input matInput (blur)="answer.fireNewLead === true ? onTriggerNewLead() : null" [placeholder]="answer.placeholderText" [name]="answer.propertyKey" [ngModel]="object[answer.propertyKey]" (ngModelChange)="object[answer.propertyKey]=$event" type="text">
<span matSuffix *ngIf="answer.hasSuffix">{{answer.suffixText}}</span>
</mat-form-field>
<mat-form-field floatLabel="always" class="dynamic-input" *ngIf="answer.isInput && answer.isConditional && returnConditionIsTrue(answer)">
<span matPrefix *ngIf="answer.hasSuffix">{{answer.prefixText}}</span>
<input matInput (blur)="answer.fireNewLead === true ? onTriggerNewLead() : null;" [placeholder]="answer.placeholderText" [name]="answer.propertyKey" [ngModel]="object[answer.propertyKey]" (ngModelChange)="object[answer.propertyKey]=$event" type="text">
<span matSuffix *ngIf="answer.hasSuffix">{{answer.suffixText}}</span>
</mat-form-field>
//Our Input
<div class="input-wrapper" *ngIf="answer.isInput" [style.width]="((answer.width/100) * 50) + 'rem'">
<input type="text" (blur)="answer.fireNewLead === true ? onTriggerNewLead() : null" [placeholder]="answer.placeholderText" [name]="answer.id" [(ngModel)]="responses[returnResponseIndex(answer)].value" class="input-box normal-input-box" *ngIf="!answer.isConditional && !answer.isAddressSearch && !answer.isVehicleVIN">
<input type="text" (blur)="answer.fireNewLead === true ? onTriggerNewLead() : null" [placeholder]="answer.placeholderText" [name]="answer.id" [(ngModel)]="responses[returnResponseIndex(answer)].value" class="input-box normal-input-box" *ngIf="answer.isConditional && !answer.isAddressSearch && !answer.isVehicleVIN && returnConditionTrue(answer.conditionAnswerId ? returnResponseValue(responses[returnConditionResponseIndex(answer.conditionAnswerId)]) : null, answer.conditionValue)">
</div>
you can add styles to classes that Angular Material uses (check them with inspect on chrome browser) in your styles.scss or in any other global styles file you have.
If you want to change them in each component you can create a parent class, and then penetrate the angular material classes using ::ng-deep .my-class .mat-button .mat-button-wrapper {...}
good luck! it's a lot of trial and error, but doable!
note: be aware that the styles that are applied are those with 'more' selectors... so if you see .mat-button.mat-primary .mat-button-wrapper {} in your inspect, don't simply try to override the .mat-button-wrapper because it doesn't have enough specificity, you need to use the specificity of material plus your own to override the one in place.
Although possible as others have indicated, as a development effort this is likely to take more effort and be more prone to problems than simply moving to something else. It would be extremely difficult to provide sufficient test coverage that might ensure you've done everything properly, so that something doesn't suddenly rear its ugly head in production.
If you really want to do this, create your own fork of the #angular/material project (or simply steal the source code), and rewrite all of the style code to suit your needs.
Related
I have a material date picker that functionally works just fine but has some styling issues.
I would like the text "Choose a date" to show up on the left side of the calendar icon, as it does in this example: https://material.angular.io/components/datepicker/overview
but as you can see it's like the calendar icon is pushed so far to the left that it shoves the text up.
Here is the html for this:
<mat-form-field appearance="fill" class="col-md-6">
<mat-label>Choose a date</mat-label>
<input matInput [matDatepicker]="startDate" (dateChange)="setMinEndDate($event)" [min]="today" [(ngModel)]="model.startDate">
<mat-hint>MM/DD/YYYY</mat-hint>
<mat-datepicker-toggle matIconSuffix [for]="startDate"></mat-datepicker-toggle>
<mat-datepicker #startDate></mat-datepicker>
</mat-form-field>
I have no other CSS or HTML for this. The date picker does exist inside a container class but even if I put it outside, or in a blank html page it still looks like this. I then assumed it had to be something with global styling. My app.component.css is completely blank. In my src folder in style.css I do have the global styling for angular material: #import "~#angular/material/prebuilt-themes/indigo-pink.css"; which seems to make everything else angular-material related work properly. Deleting this does not solve my problem as a global theme is required.
I am using angular material version 11.2.13 and Angular Core version 11.2.14.
What else could be causing this problem? Let me know if you need me to share anything else.
I have been searching for an easy way to make a month/year picker for an ASP.NET Core application I'm making. I found this fantastic one on jsfiddle. It uses the following resources:
bootstrap-datepicker.min.js
datepicker.min.css
bootstrap.min.js
bootstrap.min.css
Here is the code:
var startDate = new Date();
var fechaFin = new Date();
var FromEndDate = new Date();
var ToEndDate = new Date();
$('.from').datepicker({
autoclose: true,
minViewMode: 1,
format: 'mm/yyyy'
}).on('changeDate', function(selected) {
startDate = new Date(selected.date.valueOf());
startDate.setDate(startDate.getDate(new Date(selected.date.valueOf())));
$('.to').datepicker('setStartDate', startDate);
});
$('.to').datepicker({
autoclose: true,
minViewMode: 1,
format: 'mm/yyyy'
}).on('changeDate', function(selected) {
FromEndDate = new Date(selected.date.valueOf());
FromEndDate.setDate(FromEndDate.getDate(new Date(selected.date.valueOf())));
$('.from').datepicker('setEndDate', FromEndDate);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.0/css/datepicker.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.0/js/bootstrap-datepicker.min.js"></script>
<div class="form-group">
<label>First check in:</label>
<input type="text" class="form-control form-control-1 input-sm from" placeholder="CheckIn">
</div>
<div class="form-group">
<label>First check out:</label>
<input type="text" class="form-control form-control-2 input-sm to" placeholder="CheckOut">
</div>
<br/>
<div class="form-group">
<label>Second check in:</label>
<input type="text" class="form-control form-control-1 input-sm from" placeholder="CheckIn">
</div>
<div class="form-group">
<label>Second check out:</label>
<input type="text" class="form-control form-control-2 input-sm to" placeholder="CheckOut">
</div>
I have made this work in my project in Visual Studio, however, it doesn't seem to be able to find the classes "form-control-1" (and 2) and "from" and so it gives me a little squiggly line indicating so.
I started looking through all the css files included and I cannot find a reference to those classes in any file. If I remove them, the month selector does not work. Can someone help me understand where that functionality is coming from? Does anyone know where those classes are defined?
The from and to are not being used for styling, they are being used in the code that you posted. $('.from').datepicker() $('.to').datepicker().
You can safely delete the form-control-1 and form-control-2 classes.
Those classes can be fuctional classes, not attached to any styling but used to select or manipulate the elements.
Thats probably why you wont find anything. Search through the js files and you will find something.
Since removing the class breaks the functionality, it's probably being referenced from JS. It may be that the JS is calculating the name of the class, something like "form-control " + i for example.
Your best bet to see where this is defined is to use the browser inspector. For example, in Chrome, right-click the page and choose "inspect" to get this UI, which shows you each css class and where they are declared or re-declared in the css hierarchy.
When using Javascript it can be very useful to use CSS classes which are not attached to any styling, but are instead used as semantic references for jQuery selectors to use later.
This can be very useful when trying to attach multiple semantic meanings to an element. You can have one element can have many semantic tags. I use this in complex components to be able to dynamically tag elements that I can later manipulate or check the class name. This is especially useful if you are generating elements from a server-side language and trying to tag them semantically so that they can be manipulated later from Javascript/jQuery. It think it is much easier to add a dynamic class string from the server side than to put in data attributes.
One example of this that I use is for validation information to be attached to an element. I generate the elements in a server-side class (including what type of validation it should have) which outputs a CSS class string, then when I submit the form in Javascript, I get all elements with specific classnames and check if their contents match the validation type.
The code sample you posted does a similar thing, where it wants to use a jQuery plugin on all elements with a certain class. Instead of direct styling, it uses them as semantic markers that those elements should be transformed in a certain way to be datepickers (which are documented here: https://jqueryui.com/datepicker/). Code for jQueryUI uses this a lot to be able to simplify which elements should be used-- and it can be easier to add new elements that are datepickers, since you simply add a class to the new one instead of having to add a new jQuery reference to it (especially if you don't know exactly how many of them there will be on the page when you write the Javscipt code).
If you are ever in a similar instance and looking for a different way to store data on elements without inadvertent effects and it is pure Javascript without server side rendering, data-* attributes in HTML5 are a way to do it (and a simple library could be developed to add them to elements from a server side language). Just use jQuery selectors with jQuery("[data-mytagname=someValue]") to select.
A word of caution that if you use classes like this as semantic tags, I would be careful to avoid commonly used class names, since you could inadvertently get extra styling when a co-worker (or yourself) decides to use that in an element. ;)
We have to be ADA compliant on our site. One of the things they look for is every form must have a label tag. The code has a label tag in the right place, but then when the javascript loads on the page, a span tag gets between the tag and the search field making it no longer compliant. I don't see a way to add a label. I was curious if anyone else had a suggestion for this or is there an alternative to typeahead that will work? In order to be compliant it must look like
<label for="search">Search: </label>
<input type="text" name="search" id="search"/>
For example the way it works now looks like...
<label for="search">Search: </label>
<span class="twitter-typeahead">
<input type="text" name="search" id="search"/>
</span>
There is no option to change the span tag that wraps your input. You can see where it is hardcoded in the source code here. Unfortunately, typeahead is no longer maintained either, so there will not be a future option to customize this.
However, you can always modify the code yourself. Either in the www.js file that I linked to (if you compile yourself) or in the bundle, find the buildHtml() function and change that line to an empty string.
function buildHtml(c) {
return {
wrapper: '',
menu: '<div class="' + c.menu + '"></div>'
};
}
I don't know if this will have unknown repercussions elsewhere in typeahead, but I just tried it on a page and everything seemed to be working fine.
I'm a big fan of angularjs, I started lately to use it in all of my 'coding for fun' projects.
I have a big curiosity:
I have a two inputs, one disabled by a ng-disabled directive and the other disabled with an html tag (A better illustration in this link):
//...
<input type="text" disabled value="This is an html input text disabled" />
<input type="text" ng-disabled="true" value="disabled with angular js directive" />
//...
Using the browser ability I can right click on the input and remove the disabled and ng-disabled tags but only the one with the disabled tag would be editable, the other one will still be tracked by angular even when ng-disabled directives has been removed.
So, When and Why should I prefer using ng directives over native html tags? Which could be the impact of letting angular track all these actions? is it really worth to use it everywhere?
Use the native html 'disabled' if the element should always be disabled. (static, for example if you want to provide an input with text and never let the user change it)
Use angular if it should change based on variables value in the scope.
For example, say a button should change the state of an input.
<input type="button" ng-click="inpDisabled = true" >Disable Input</input>
<input type="text" ng-disabled="inpDisabled" />
live example
No harm will come if you still use ng-disabled="true" but it's redundant.
If you want to make directive static, you shoud use native html
<your-tag disable><your-tag>
against
<your-tag ng-disabled="true"><your-tag>
But AngularJS does not work this way, you shoud initialize your application and controller, then pass a variable as parameter to your directive:
JS:
$scope.isDisabled = true;
HTML:
<your-tag ng-disabled="isDisabled"><your-tag>
You shoud read more tutorials to make things clear
I have an app with many forms. Each field has several HTML elements, so I thought I could extract some directives (one per type of field) to keep my forms tidy.
I've created a sample app to demonstrate the problem, but I'm getting inconsistent behavior. In the sample app, a <link /> element replaces the <input />. In my real app, <input /> just gets removed from the DOM completely. I feel like this should be easy; why doesn't it work?
To answer your stated question, it's because you told it to, with ng-transclude. That replaces the contents of the tag with the original element, which I don't think you wanted; you probably wanted the original contents to be transcluded as the label instead.
This is probably what you're looking for:
<div class="form-group" >
<label for="{{htmlId}}" ng-transclude></label>
<input id="{{htmlId}}" class="form-control" type="text" ng-model="model" />
<span ng-repeat="error in errors">{{error}}</span>
</div>
I've moved the tranclusion into the label. While this works, I would also recommend the style of actually passing a label attribute, rather than transclude it, just for the sake of having a consistent API and simpler code; it's functionally equivalent, though, so don't let me bully you.
Also, you've got a few errors in your .js as well. First, you want to use = in your scope instead of &
scope: {
model: '=',
errors: '='
},
& is used to pass methods, while = is used for objects (this is a simplification). Since your model and errors are objects, you'll want to use = instead.
Finally, in your example, your html template and your directive's template don't have the same name... you've got an extra 's' in your .js, but that's probably just in the plunker and not your real app.