Custom class names for Material.io components - javascript

I am implementing Material.io for a web project, and looking to make the class names that are used by Material.io more project related. Currently 'mdc-' is pre-pended to each class and I would like to have this as something a bit more custom to the project.
(A simple code comparison added below).
Taking the Material.io default output of this:
<button class="mdc-button">
<div class="mdc-button__ripple"></div>
<span class="mdc-button__label">Button</span>
</button>
And customising the block element class name to the following:
(company used as an example, the desired company name or abbreviation would be used in replace of this)
<button class="company-button">
<div class="company-button__ripple"></div>
<span class="company-button__label">Button</span>
</button>
Has anyone tried this? I am struggling to find a workaround and it might well be an indication that this is a bad idea.

Classic case of overthinking, I resolved my issue with a simple extend.
See example below:
#import "#material/chips/mdc-chips";
.company-chips {
#extend .mdc-chips;
}

Related

EmberJS template component suddenly not rendering on page

I'm following this Ember tutorial and I've suddenly run into an issue where my rental-listing.hbs template component stops rendering. It started when I began implementing the map service.
I don't understand where this could be happening. I've copied the code from parts of the GitHub repository that I thought were relevant but to no avail.
I have a rental.hbs template that looks like so:
<div class="jumbo">
<div class="right tomster"></div>
<h2>Welcome!</h2>
<p>We hope you find exactly what you're looking for in a place to stay.</p>
{{#link-to "about" class="button"}}
About Us
{{/link-to}}
</div>
{{outlet}}
Which in turn has a template component called rental-listing.hbs:
<article class="listing">
<a
onclick={{action "toggleImageSize"}}
class="image {{if this.isWide "wide"}}"
role="button"
>
<img src={{this.rental.image}} alt="">
<small>View Larger</small>
</a>
<div class="details">
<h3>{{link-to this.rental.title "rentals.show" this.rental class=this.rental.id}}</h3>
<div class="detail owner">
<span>Owner:</span> {{this.rental.owner}}
</div>
<div class="detail type">
<span>Type:</span> {{rental-property-type this.rental.category}} - {{this.rental.category}}
</div>
<div class="detail location">
<span>Location:</span> {{this.rental.city}}
</div>
<div class="detail bedrooms">
<span>Number of bedrooms:</span> {{this.rental.bedrooms}}
</div>
</div>
<LocationMap #location={{this.rental.city}}/>
</article>
The only thing I have added to the above is the line <LocationMap #location={{this.rental.city}}/> but it still doesn't work if I remove it.
The console shows me no errors and I can actually see I am getting the three dummy objects I want from Mirage:
So I'm definitely getting the objects and from what I see I'm doing everything necessary in the templates to render it but they aren't. Should I be looking somewhere else?
Are you able to provide a link to your example? By having each piece of the ember application you mention it would be best to answer definitely. I can give a general answer with strategies for debugging the template.
The conventions behind ember.js make understanding the "whys" frustrating at first and possibly opaque. Ember's handlebars implementation governs how values are populated and accessed within templates using very specific rules. Ember treats templates (handlebars files) differently depending on whether it is for a route or component. Component's have an isolated context and must receive values by explicit passing in or dependency injection. Then, you can use such values in a component's template by accessing those properties with {{this.somePassedInValue}}.
In the super-rentals app, it appears the rental index route invokes the components responsible for displaying the individual units. I found this in app/templates/rentals/index.hbs.
<li><RentalListing #rental={{rentalUnit}} /></li>
The route template iterates over the list of filteredResults. Each of these is the rentalUnit. A good first step would be to use the {{log}} helper to print out that the value of rentalUnit to ensure it is what you expect.
Alternatively, you could try cloning https://github.com/ember-learn/super-rentals and applying the changes you want to make step by step from the master branch. By doing so, you could easily undo a single change to see what caused something to not show up as expected.
<LocationMap #location={{this.rental.city}}/>
to be written as below
<LocationMap #location={{this.rentals.city}}/>
may be typo error.
also repeat this for there place in that template.
Because the model name in the console is rentals not rental

How to remove extra wrapping elements in the rendered HTML?

I started learning angular 5 3 days ago so I'm quite new at it. I also use angularJS and React to develop applications and I think I don't understand how angular 5 components fully work. If I create for example a custom button that has a custom text inside (I'm not saying this should be done this way but it's a simple example that shows my point) like this:
<app-button>
<app-text>
My Text
</app-text>
</app-button>
The rendered DOM results in:
<app-button>
<button>
<app-text>
<span>
My Text
</span>
</app-text>
</button>
</app-button>
which is unreadable, I wanted to know if there's a way to remove this wrapping elements and just place the components layout replacing the tags resulting in the following structure:
<button>
<span>
My Text
</span>
</button>
If there's no way of removing them what are your suggestions? thanks!
Angular components are directives with templates. According to this:
Directive configuration #Directive({ property1: value1, ... })
selector: '.cool-button:not(a)' Specifies a CSS selector that
identifies this directive within a template. Supported selectors
include element, [attribute], .class, and :not().
So component selectors can be also attribute selectors. For your example, instead of writing this:
parent.component.html:
<app-button>
<app-text>
My Text
</app-text>
</app-button>
write this:
parent.component.html:
<button app-button>
<span app-text>My Text</span>
</button>
where :
app-button.component.ts
...
selector: '[app-button]',
template: `<ng-content></ng-content>
...
app-text.component.ts
...
selector: '[app-text]',
template: `<ng-content></ng-content>`
...
this would be rendered as you expected:
Update after your comment about styling those buttons:
To style the buttons from inside the button component, and set class in parent component, use :host-context pseudo-class. It is not deprecated and works well
button.component.css
:host-context(.button-1) {
background: red;
}
:host-context(.button-2) {
background: blue;
}
app.component.html
<button app-button class="button-1">
<span app-text>My Text</span>
</button>
<button app-button class="button-2">
<span app-text>My Text</span>
</button>
Here is the DEMO
I had a similar issue. I'll provide my solution in case someone else has the same problem.
My component should be able to be used either within other components or as a route from <router-outlet></router-outlet>. When I used the selector as an attribute [my-component] things worked perfectly provided it was used within other components. But when created by <router-outlet></router-outlet> a <div> were created automatically.
To avoid that, we can simply use multiple selectors, and consider that the selectors can be combined.
Consider this: I want my component to use the attribute my-component and if it ever should be created by the <router-outlet></router-outlet> it should be wrapped in a <section></section>. To achieve this simply use:
#Component(
selector: 'section[my-component], my-component',
...
)
The result will be, if used inside another tag:
<whatevertag my-component>
... component content ...
</whatertag>
If used as a route:
<section my-component>
... component content ...
</section>

Angular : template changing depending on javascript value

I am building an angular app, with templates changing depending on with ngscope as seen on the samples below.
<label class="btn btn-default">
<input id="cacher" value="settings" type="radio" data-ng-model="user.status">Settings
</input>
</label>
and here i'm calling my html template userPageSettings
<div id="wrapper" ng-switch="user.status">
<div ng-switch-when="settings">
<user-page-settings></user-page-settings>
</div>
</div>
Trouble is, i'm trying to get access to the templates (and the correct route) through a dropdown in the navbar, which is supposed to do exactly the same thing as my normal menu. But if i simply call the templates from my navbar they will be shown on the current page, therefore at the incorrect route.
In my navbar code i'm doing the following, which is bringing me back to the correct route, but showing me my default template (aka home, not shown here, but called through the same method and has the number 6)
<li role="menuitem">Settings</li>
The number "1" (and the others using 2,3 etc) are hashed in my javascript and put into a variable. I would like to make my templates appear depending on those numbers.
Any ideas how ??
:) Thank you !!

Angular-translate function not working as expected

I'm including translation to my website using angular-translate
So I have this piece of code:
<td class="nav-button">
<a href="{{button.location}}" class ="'{{button.clazz}}'" ng-click="showDetails = !showDetails" >
{{button.text}}
<div ng-show="button.subButtons.length && showDetails" ng-repeat="subButton in button.subButtons">
<a href="{{subButton.location}}" class="'{{button.clazz}}'" translate>
{{subButton.text}}
</a>
</div>
</a>
</td>
The sub-buttons appear normally and the translation works just right. But only translating the subButtons.
The problem is : I want to translate the {{button.text}} as well
But when I add the translate to the first <a>, neither the features works.
I've tried several ways to fix this but I failed.
Somebody that maybe had the same problem could help ? Thanks.
angular translate is a filter
{{button.text|translate}}
I am curious to what subButton.text contains. It needs to contain the key of the translation value that you are looking for. For example, my translations file looks like this:
{
"SUB_BUTTON": "Hello there, this is the sub button"
}
I can create a button in multiple ways.
via filter
<button>{{"SUB_BUTTON" | translate}}</button>
via directive 1
<button translate="SUB_BUTTON"></button>
via directive 2
<button translate>"SUB_BUTTON"</button>
For more info please read further on the angular-translate Docs

Most Angular way to add class on click

I'm building an interface with a lot of toggles to control what data is being filtered in a different part of an App's search results. Here is a codepen of it: Here
Coming from a jQuery/Backbone background, what is the most Angular way of toggling the 'active' state of any/all of the filter items? Essentially, almost any <li> tag presented here is a toggle-able feature.
In jQuery, I would put a listener on the view and wait for any click events to bubble up and toggle an 'active' class on the event.target. I want to do it the best way with Angular.
(Also, this is my first Angular project.. I am probably doing all sorts of things the wrong way. Apologies in advance.)
Edit: To clarify the question, I have an App Interface with 20+ possible filter attributes to control a separate module on the page. Every time someone toggles one of these filter attributes, I want to add/remove an 'active' class. Do I put an 'ng-click="function(...)"' in the ng-repeat for each controller? Or is there an easier way to manage this module-wide behavior (a la event bubbling, like in Backbone/jQuery) ?
Thanks!
You can do something like this:
<section ng-init="active = 'areaFoo'">
<div ng-class="{active:active == 'areaFoo'}" ng-click="active = 'areaFoo'"></div>
<div ng-class="{active:active == 'areaBar'}" ng-click="active = 'areaBar'"></div>
</section>
It will populate $scope.active for you, and is very angular as it leverages existing directives, manages the state on scope, and does not leverage dom api's or events outside of directives. There is really no need to involve the controller here, as its display logic.
Learn more about ng-class here.
Multiple active elements
<section>
<div ng-class="{active:areaFoo}" ng-init="areaFoo = true">
<button ng-click="areaFoo = true">activate</button>
<button ng-click="areaFoo = false">de activate</button>
</div>
<div ng-class="{active:areaBar}" ng-init="areaBar = false">
<button ng-click="areaBar = true">activate</button>
<button ng-click="areaBar = false">de activate</button>
</div>
<div ng-class="{active:areaBar}" ng-init="areaBaz = false">
<button ng-click="areaBaz = true">activate</button>
<button ng-click="areaBaz = false">de activate</button>
</div>
</section>
you could also toggle with something like this ng-click="areaFoo = !areaFoo"
I was able to come up with a solution I'm ok with, for anyone curious you can see a demo Here.
Here are the relevant code snippets:
<li ng-repeat='category in data' ng-class='{active: category.isActive}' ng-click='toggleActive(category)' >
<span class='solr-facets-filter-title'>{{category.catTitle}}</span>
<span class='solr-facets-filter-count'>{{category.catResults}}</span>
</li>
An ng-click calls a method on the Controller, toggleActive(category). The current data model gets sent to the method. In the JS:
$scope.toggleActive = function(category){
category.isActive = !category.isActive;
}
The function returns the opposite of the isActive attribute back to the li in question: an ng-class adds the active class for a truthy state of isActive.
I'm not a huge fan of how I have to adjust the data model with flags for active/inactive states like this, but it ends up working out for the best in this case. I can push those isActive states back to the $scope so that other parts of the App can run queries based on that information.

Categories