1676672640
In this article, we will see to fixed class "DOMDocument" not found in laravel. Also, class 'domdocument' not found php 7, and class 'domdocument' not found php 8. class 'domdocument' not found php artisan. The DOMDocument class represents an entire HTML or XML document.
Also, we will see how to install php-dom and php-xml extensions in ubuntu using the terminal.
So, let's see fixed: class "DOMDocument" not found in laravel, class domdocument not found in laravel, class 'domdocument' not found laravel 9, class 'domdocument' not found ubuntu and how to resolve domdocument class not found in php.
Run the following command to install php-dom and php-xml.
sudo apt-get install php-dom
sudo apt-get install php-xml
Install php-dom in PHP 8.2
Run the following command and install php8.2-dom and php8.2-xml.
sudo apt-get install php8.2-dom
sudo apt-get install php8.2-xml
Install php-dom in PHP 8.1
Run the following command and install php8.1-dom and php8.1-xml.
sudo apt-get install php8.1-dom
sudo apt-get install php8.1-xml
Install php-dom in PHP 8.0
Run the following command and install php8.0-dom and php8.0-xml.
sudo apt-get install php8.0-dom
sudo apt-get install php8.0-xml
Install php-dom in PHP 7.4
Run the following command and install php7.4-dom and php7.4-xml.
sudo apt-get install php7.4-dom
sudo apt-get install php7.4-xml
Install php-dom in PHP 7.3
Run the following command and install php7.3-dom and php7.2-xml.
sudo apt-get install php7.2-dom
sudo apt-get install php7.2-xml
Install php-dom in PHP 7.2
Run the following command and install php7.2-dom and php7.2-xml.
sudo apt-get install php7.2-dom
sudo apt-get install php7.2-xml
Original article source at: https://websolutionstuff.com/
1671890428
Routing is the most common and important feature in each and every application perhaps it is a web or a mobile one. So, In this blog, we are going to talk about the ActivatedRouteSnapshot and its properties which helps the developer to establish the roadmap of routing in an application.
So before diving deep into ActivatedRouteSnapshot let’s start we a question what is ActivatedRouteSnapshot?
It is a class that Contains information about a route associated with a component loaded in an outlet at a particular moment in time.
Also, we can traverse the UrlTree.
@Component({templateUrl:'app-home-template.html'})
class HomeComponent {
constructor(route: ActivatedRoute) {
const id: string = route.snapshot.params.id;
const url: string = route.snapshot.url.join('');
const user = route.snapshot.data.user;
console.log('id',id);
console.log('url',url);
console.log('user',user);
}
}
When any user hits a new route in an Angular application, the routing uses the browser URL to navigate to the corresponding route and showcase the particular component in the DOM(Document Object Model).
In parallel, it collects the route information to create the instance for that particular route with the help of ActivatedRouteSnapshot.
This instance created through ActivatedRouteSnapshot contains all the information about that route, data, and its parameters. Basically, we can say that this instance helps the ActivatedRouteSnapshot in deciding which components should be rendered for a given route.
ActivatedRouteSnapshot have several parameters in routing and some of them are Showcase below:
Url | UrlSegment[] | The URL segments matched by this route |
queryParams | Params | The query parameters shared by all the routes |
Fragment | string | The URL fragment shared by all the routes |
Data | Data | Information for the current route |
Outlet | string | Outlet name of the route |
routeConfig | Route | configuration object for that route |
urlSegment | UrlSegmentGroup | a parsed URL segment group |
For the last stable version of Angular the Router API uses the ActivatedRoute to create the UrlTree and this route must be active and need to appear in the UrlTree. i.e it cannot be empty.
Because of this current process, the UrlSegment of the ActivatedRoute is looked up in the currently active UrlTree of the router. And if the router is empty the UrlTree will not create and shows a failure.
So to resolve the issue the ActivatedRoute initiated a new functionality that allows it to create a UrlTree from an ActivatedRouteSnapshot.
Below are the code structures for both the scenario :
@Injectable({ providedIn: 'root' })
export class LoginActivatedGuard implements CanActivate {
constructor(private router: Router, private route: ActivatedRoute) { }
canActivate(route: ActivatedRouteSnapshot) {
if(checkData(route)) {
this.router.navigate(['../route2'], { relativeTo: this.route });
return false;
}
return true;
}
}
const routes: Routes = [{
path: 'home',
component: HomeComponent,
children: [
{
path: 'route1',
component: RouteOneComponent,
canActivate: [LoginActivatedGuard]
},
{
path: 'route2',
component: RouteTwoComponent
}
]
}]
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, createUrlTreeFromSnapshot } from
'@angular/router';
@Injectable({ providedIn: 'root' })
export class LoginActivatedGuard implements CanActivate {
canActivate(route: ActivatedRouteSnapshot) {
if(checkData(route)) {
return createUrlTreeFromSnapshot(route, ['../route2']);
}
return true;
}
}
The CreateUrlTreeFromSnapshot
function takes an ActivatedRouteSnapshot
, commands
, and optional queryParams
and fragments
and returns a UrlTree
.
So after the above, I can say that the ActivatedStateSnapshot provides ease to the routing and helps us to retrieve data/information about the current, and previous route and it also helps us to create the UrlTree.
To learn more about ActivatedRouteSnapshot, ActivatedRoute, and ActivatedstateSnapshot, refer here.
I hope this blog helped you learn something new and if you liked this blog. Please share it with your friends and colleagues and For more updates on such topics, please follow our LinkedIn page- FrontEnd Studio.
Original article source at: https://blog.knoldus.com/
1671187392
Selectors are commonly used in stylesheets. The following example locates all <p>
paragraph elements and changes the font weight to bold:
p {
font-weight: bold;
}
You can also use selectors in JavaScript to locate DOM nodes:
Pseudo-class selectors target HTML elements based on their current state. Perhaps the most well known is :hover
, which applies styles when the cursor moves over an element, so it’s used to highlight clickable links and buttons. Other popular options include:
:visited
: matches visited links:target
: matches an element targeted by a document URL:first-child
: targets the first child element:nth-child
: selects specific child elements:empty
: matches an element with no content or child elements:checked
: matches a toggled-on checkbox or radio button:blank
: styles an empty input field:enabled
: matches an enabled input field:disabled
: matches a disabled input field:required
: targets a required input field:valid
: matches a valid input field:invalid
: matches an invalid input field:playing
: targets a playing audio or video elementBrowsers have recently received three more pseudo-class selectors…
Note: this was originally specified as :matches()
and :any()
, but :is()
has become the CSS standard.
You often need to apply the same styling to more than one element. For example, <p>
paragraph text is black by default, but gray when it appears within an <article>
, <section>
, or <aside>
:
/* default black */
p {
color: #000;
}
/* gray in <article>, <section>, or <aside> */
article p,
section p,
aside p {
color: #444;
}
This is a simple example, but more sophisticated pages will lead to more complicated and verbose selector strings. A syntax error in any selector could break styling for all elements.
CSS preprocessors such as Sass permit nesting (which is also coming to native CSS):
article, section, aside {
p {
color: #444;
}
}
This creates identical CSS code, reduces typing effort, and can prevent errors. But:
:is()
provides a native CSS solution which has full support in all modern browsers (not IE):
:is(article, section, aside) p {
color: #444;
}
A single selector can contain any number of :is()
pseudo-classes. For example, the following complex selector applies a green text color to all <h1>
, <h2>
, and <p>
elements that are children of a <section>
which has a class of .primary
or .secondary
and which isn’t the first child of an <article>
:
article section:not(:first-child):is(.primary, .secondary) :is(h1, h2, p) {
color: green;
}
The equivalent code without :is()
required six CSS selectors:
article section.primary:not(:first-child) h1,
article section.primary:not(:first-child) h2,
article section.primary:not(:first-child) p,
article section.secondary:not(:first-child) h1,
article section.secondary:not(:first-child) h2,
article section.secondary:not(:first-child) p {
color: green;
}
Note that :is()
can’t match ::before
and ::after
pseudo-elements, so this example code will fail:
/* NOT VALID - selector will not work */
div:is(::before, ::after) {
display: block;
content: '';
width: 1em;
height: 1em;
color: blue;
}
:where()
selector syntax is identical to :is()
and is also supported in all modern browsers (not IE). It will often result in identical styling. For example:
:where(article, section, aside) p {
color: #444;
}
The difference is specificity. Specificity is the algorithm used to determine which CSS selector should override all others. In the following example, article p
is more specific than p
alone, so all paragraph elements within an <article>
will be gray:
article p { color: #444; }
p { color: #000; }
In the case of :is()
, the specificity is the most specific selector found within its arguments. In the case of :where()
, the specificity is zero.
Consider the following CSS:
article p {
color: black;
}
:is(article, section, aside) p {
color: red;
}
:where(article, section, aside) p {
color: blue;
}
Let’s apply this CSS to the following HTML:
<article>
<p>paragraph text</p>
</article>
The paragraph text will be colored red, as shown in the following CodePen demo.
The :is()
selector has the same specificity as article p
, but it comes later in the stylesheet, so the text becomes red. It’s necessary to remove both the article p
and :is()
selectors to apply a blue color, because the :where()
selector is less specific than either.
More codebases will use :is()
than :where()
. However, the zero specificity of :where()
could be practical for CSS resets, which apply a baseline of standard styles when no specific styling is available. Typically, resets apply a default font, color, paddings and margins.
This CSS reset code applies a top margin of 1em
to <h2>
headings unless they’re the first child of an <article>
element:
/* CSS reset */
h2 {
margin-block-start: 1em;
}
article :first-child {
margin-block-start: 0;
}
Attempting to set a custom <h2>
top margin later in the stylesheet has no effect, because article :first-child
has a higher specificity:
/* never applied - CSS reset has higher specificity */
h2 {
margin-block-start: 2em;
}
You can fix this using a higher-specificity selector, but it’s more code and not necessarily obvious to other developers. You’ll eventually forget why you required it:
/* styles now applied */
article h2:first-child {
margin-block-start: 2em;
}
You can also fix the problem by applying !important
to each style, but please avoid doing that! It makes further styling and development considerably more challenging:
/* works but avoid this option! */
h2 {
margin-block-start: 2em !important;
}
A better choice is to adopt the zero specificity of :where()
in your CSS reset:
/* reset */
:where(h2) {
margin-block-start: 1em;
}
:where(article :first-child) {
margin-block-start: 0;
}
You can now override any CSS reset style regardless of the specificity; there’s no need for further selectors or !important
:
/* now works! */
h2 {
margin-block-start: 2em;
}
The :has()
selector uses a similar syntax to :is()
and :where()
, but it targets an element which contains a set of others. For example, here’s the CSS for adding a blue, two-pixel border to any <a>
link that contains one or more <img>
or <section>
tags:
/* style the <a> element */
a:has(img, section) {
border: 2px solid blue;
}
This is the most exciting CSS development in decades! Developers finally have a way to target parent elements!
The elusive “parent selector” has been one of the most requested CSS features, but it raises performance complications for browser vendors, and therefor has been a long time coming. In simplistic terms:
<body>
.Assuming the vendors have resolved performance issues, the introduction of :has()
permits possibilities that would have been impossible without JavaScript in the past. For example, you can set the styles of an outer form <fieldset>
and the following submit button when any required inner field is not valid:
/* red border when any required inner field is invalid */
fieldset:has(:required:invalid) {
border: 3px solid red;
}
/* change submit button style when invalid */
fieldset:has(:required:invalid) + button[type='submit'] {
opacity: 0.2;
cursor: not-allowed;
}
This example adds a navigation link submenu indicator that contains a list of child menu items:
/* display sub-menu indicator */
nav li:has(ol, ul) a::after {
display: inlne-block;
content: ">";
}
Or perhaps you could add debugging styles, such as highlighting all <figure>
elements without an inner img
:
/* where's my image?! */
figure:not(:has(img)) {
border: 3px solid red;
}
Before you jump into your editor and refactor your CSS codebase, please be aware that :has()
is new and support is more limited than for :is()
and :where()
. It’s available in Safari 15.4+ and Chrome 101+ behind an experimental flag, but it should be widely available by 2023.
The :is()
and :where()
pseudo-class selectors simplify CSS syntax. You’ll have less need for nesting and CSS preprocessors (although those tools provide other benefits such as partials, loops, and minification).
:has()
is considerably more revolutionary and exciting. Parent selection will rapidly become popular, and we’ll forget about the dark times! We’ll publish a full :has()
tutorial when it’s available in all modern browsers.
If you’d like to dig in deeper to CSS pseudo-class selectors — along with all other things CSS, such as Grid and Flexbox — check out the awesome book CSS Master, by Tiffany Brown.
Original article source at: https://www.sitepoint.com/
1670094900
CSS classes are very helpful when need to add same style on multiple HTML elements.
Sometimes need to perform an action based on a class element has.
In this tutorial, I show how you can check if element has a specific class using JavaScript with examples.
HTML
<div id='divel' >
and added class red
to it.hasClass()
function. Pass <div >
instance and class name that needs to check.red
class on <div id='divel' >
.<div id='result1'></div>
using JavaScript.JavaScript
hasClass()
function.classList.contains()
to search on element. It returns a boolean value.true
then display True
message to <div id='result1'>
otherwise, display False
message.Completed
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>How to Check if element has class in JavaScript</title>
</head>
<body>
<style>
.content{
width: 100px;
height: 100px;
color: white;
}
.red{
background: red;
}
</style>
<h2>Search class on single element</h2>
<div class='content red' id='divel' ></div>
<br><br>
<input type='button' value="Has class - red" onclick="hasClass(document.getElementById('divel'),'red')">
<br><br>
<b>Result : </b><br>
<div id='result1'></div>
<!-- Script -->
<script type="text/javascript">
// Single search
function hasClass(el,classname){
if(el.classList.contains(classname)){
document.getElementById('result1').innerHTML = 'True';
}else{
document.getElementById('result1').innerHTML = 'False';
}
}
</script>
</body>
</html>
HTML
Created 3 <div class='content' >
elements. 2 <div >
has red
class and 1 has blue
class. 1 button to search red
class.
Display <div >
ids that has red
class in <div id='result2'>
.
JavaScript
Create 2 functions –
This function takes 2 parameters – element instance and search class name. Search classname
using classList.contains()
and return true
and false
.
<div >
ids that has red
class.This function calls on button click. This function takes 1 parameter – search class name. Loop on <div >
that has class name content. Pass <div >
instance and classname
variable in hasClass()
function.
If it returns true
then read <div >
id
attribute and append in ids
variable.
Display <div >
ids in <div id='result2'>
.
Completed Code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>How to Check if element has class in JavaScript</title>
</head>
<body>
<style>
.content{
width: 100px;
height: 100px;
display: inline-block;
color: white;
}
.red{
background: red;
}
.blue{
background: blue;
}
</style>
<h2>Search class on multiple elements</h2>
<div class='content red' id='div1'>div1</div>
<div class='content blue' id='div2'>div2</div>
<div class='content red' id='div3'>div3</div><br><br>
<input type='button' value="Has class - red" id='check' onclick="checkClass('red');">
<br><br>
<b>Result</b><br><br>
<div id='result2'></div>
<script type="text/javascript">
// Search class
function hasClass(el,classname){
if(el.classList.contains(classname)){
return true;
}else{
return false;
}
}
// Multiple search
function checkClass(classname){
var div = document.getElementsByClassName('content');
var totalel = div.length;
var ids = "";
for(var i=0;i<totalel;i++){
if(hasClass(div[i],classname)){
var divid = div[i].getAttribute('id');
ids += divid + ", ";
}
document.getElementById('result2').innerHTML = ids;
}
}
</script>
</body>
</html>
I hope using the examples you have successfully implemented class searching using JavaScript.
You can view this tutorial to know class searching using jQuery.
If you found this tutorial helpful then don't forget to share.
Original article source at: https://makitweb.com/
1669620984
The Gson library is a Java library developed by Google that allows you to serialize and deserialize Java objects to their JSON representation.
The library can also be used in Kotlin to convert Kotlin class
and data class
instances into their JSON representations.
First, you need to add the Gson library as a dependency to your project. If you’re developing an Android application, you can add the dependency in your app/build.gradle
file:
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
// ...
implementation 'com.google.code.gson:gson:2.8.9'
}
Or if you’re developing a Kotlin app with Maven, add the following to your pom.xml
file <dependencies>
tag:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
Once you sync the dependencies for your project, the Gson library should be available for you to use.
To convert a Kotlin class
instance into its JSON instance, you need to call the Gson().toJson()
method and pass the class instance as its parameter.
Suppose you have a User
data class with the following definition:
data class User(
val firstName: String,
val lastName: String
)
You can create a JSON representation of the User
data class instance as follows:
val myUser = User("Nathan", "Sebhastian")
val jsonString = Gson().toJson(myUser)
println(jsonString)
The jsonString
variable value would be as follows:
{"firstName":"Nathan","lastName":"Sebhastian"}
Both Kotlin class
and data class
instances can be serialized in the same way.
Gson can also be used to convert a JSON string back into Kotlin class instance by calling the fromJson()
method.
The following example takes the userJson
string and converts it into a Kotlin object:
val userJson = """
{
"firstName": "Arya",
"lastName": "Stark"
}"""
val myUser = Gson().fromJson(userJson, User::class.java)
println(myUser.firstName) // Arya
println(myUser.lastName) // Stark
The fromJson()
method accepts two parameters:
And that’s how you deserialize a JSON string using the Gson library.
By default, Gson will use the class field names for your JSON keys.
You can define custom JSON keys for each of your field names using the @SerializedName
annotation as follows:
data class User(
@SerializedName("first_name")
val firstName: String,
@SerializedName("last_name")
val lastName: String
)
When you call the toJson()
method, the JSON keys will use the annotations as shown below:
val myUser = User("Nathan", "Sebhastian")
val jsonString = Gson().toJson(myUser)
println(jsonString)
// {"first_name":"Nathan","last_name":"Sebhastian"}
The same goes when you call the fromJson()
method.
And that’s how you can use the Gson library with Kotlin class instances.
When the only purpose of your Kotlin class
is to provide a blueprint for JSON values, it’s recommended to create a data class
instead of a regular class
.
Learn more about Kotlin data class here.
Original article source at: https://sebhastian.com/
1669613100
Android Studio provides you with a helper menu to generate getters and setters for class
fields.
Here’s how to generate getters and setters for Java class
fields:
command + N
for MacAlt + Insert
for Windows and Linux.In the following screenshot, you can see the Generate setter and getter option highlighted from the Generate menu:
Android Studio generate getter and setter option
You can also reach the same menu by right-clicking anywhere inside your class
in the code editor and select the Generate… option.
A context menu should appear as shown below:
Android Studio Generate context menu
Alternatively, you can also use the top bar Code menu to generate getters and setters for a class:
Code > Generate… > Getter and Setter
Inside the Getter and Setter menu, select all the fields you want to generate getters and setters methods and click OK.
You should see getters and setters generated in your code as shown below:
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
And that’s how you generate getters and setters for a Java class.
By default, Kotlin automatically generate getters and setters for all your class properties.
When you define the following code in Kotlin:
class Profile {
var name: String = "Nathan"
var age: Int = 29
}
Getters and setters will be auto-generated in your class
like this:
class Person {
var name: String = "Nathan"
var age: Int = 29
// getter
get() = field
// setter
set(value) {
field = value
}
}
In Kotlin, there’s no need to define getters and setters manually to get the class
attribute or property values.
The following Java code:
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Is equivalent to the following Kotlin code:
var name: String = ""
In Kotlin, class
fields (or properties) are always accessed through the getter and setter of that class. When you run the classname.property = value
assignment, the set()
function is called internally.
When you try to get property value using the classname.property
syntax, then the get()
function is called.
There’s no need to create private
properties with public
accessors/ mutators like in Java.
For this reason, Android Studio doesn’t provide an option to generate getters and setters for Kotlin classes.
At times, you might want to set the setters as private to prevent change outside of the class. You can do so with the following code:
class Profile {
var name: String = "Nathan"
private set
var age: Int = 29
private set
}
You need to set the access level of the setters individually for each property.
Now you’ve learned how to generate getters and setters method with the help of Android Studio. Good work! 👍
Original article source at: https://sebhastian.com/
1669460460
To check whether a class exists or not in PHP, you need to use the class_exists()
function.
Call the class_exists()
function and pass the class name as a string parameter to that function:
// 👇 check if a class named Human exists
class_exists("Human");
The function will return either true
or false
. Combine it with an if
block to create conditional branch as shown below:
if(class_exists("Human")){
print "The Human class exists";
} else {
print "Class does not exists";
}
And that’s how you check whether a class exists or not in PHP. Nice! 👍
Original article source at: https://sebhastian.com/
1669365780
To change an HTML element’s class
attribute value using JavaScript, you can use either the className
or the classList
property provided for every single HTML element.
This tutorial will help you learn how to use both methods, starting from the className
property.
The className
property allows you to fetch an HTML element’s class
attribute value as a string.
Here’s an example of how className
property works:
<body>
<p id="header" class="red">Hello World! This is a paragraph element.</p>
<script>
const paragraph = document.getElementById("header");
console.log(paragraph.className); // "red"
</script>
</body>
Now that you know how the className
property works, you can change the class
value of an element by assigning a new value to the property as follows:
<body>
<p id="header" class="red">Hello World! This is a paragraph element.</p>
<script>
const paragraph = document.getElementById("header");
paragraph.className = "yellow blue";
console.log(paragraph.className); // "yellow blue"
</script>
</body>
Using the className
property allows you to change the class
attribute value, but you need to add the previous value manually if you want to keep it.
For example, to keep the class "red"
from the <p>
element above and adds a new class named "font-large"
, you need to assign both classes as follows:
const paragraph = document.getElementById("header");
paragraph.className = "red font-large";
Even though the "red"
class is already present, you still need to assign it again, creating a small redundancy in your code.
To avoid this kind of redundancy, you can use the classList
property instead.
The classList
property is a read-only property of an HTML element that returns the class
attribute value as an array. The property also provides several methods for you to manipulate the class
attribute value.
For example, to add new class names without removing the current value, you can use the classList.add()
method.
Using the same <p>
element example above, here’s how to add the "font-large"
class without removing the "red"
element:
<body>
<p id="header" class="red">Hello World! This is a paragraph element.</p>
<script>
const paragraph = document.getElementById("header");
paragraph.classList.add("font-large");
console.log(paragraph.classList); // ["red", "font-large"]
</script>
</body>
When you want to remove an element’s class
attribute value, you can use the remove()
method, which allows you to remove()
class names as a comma-delimited string:
<body>
<p id="header" class="red">Hello World! This is a paragraph element.</p>
<script>
const paragraph = document.getElementById("header");
paragraph.classList.add("font-large");
paragraph.classList.remove("red");
console.log(paragraph.classList); // ["font-large"]
</script>
</body>
For more information on classList
property you can read the following post:
JavaScript classList() property and methods explained
And that’s how you can change the class
attribute value using the className
or classList
property methods.
Original article source at: https://sebhastian.com/
1668830580
Learn how to create a Singleton class using Kotlin with code examples
A Singleton class is a class that has only one instance as long as the application lives in the memory.
It also needs to be accessible publicly so you can share the class members between different parts of your application.
In Kotlin, a singleton class can be created by using the object
keyword.
An object
in Kotlin gets initialized during the first it was required by your source code.
For example, suppose you create an object named Util
as shown below:
object Util {
val name = "Nathan"
fun hello() {
println("Hello I'm $name")
}
}
The Util
object will be initialized the first time it was called during the runtime, while subsequent calls will access the same instance.
Util.hello() // object gets initialized
println(Util.name) // use the created instance
Unlike in Java, Kotlin provides built-in support for the Singleton pattern so it’s very easy to create one.
And that’s how you create a Singleton class in Kotlin. 😉
Original article source at: https://sebhastian.com/
1668775620
Here's how you can change an element's class using jQuery
When you need to add a class name to an element using jQuery, you can use the addClass()
method.
The addClass()
method can accept multiple class names as its parameter, separated by a space:
addClass("newClass otherClass");
// adds newClass and otherClass to all matching elements
The addClass()
method can be used together with the removeClass()
method so you can change elements' classes from one another.
Here’s an example of changing a <div>
element’s classes. You need to select the right element using jQuery selector $()
method as follows:
<head>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<h1>jQuery change class tutorial</h1>
<div class="example">The first DIV element</div>
<div class="example">The second DIV element</div>
<script>
$(".example").addClass("myClass").removeClass("example");
</script>
</body>
In the example above, the two <div>
elements' classes will be changed from example
to myClass
.
You can also add and remove multiple classes at once:
<head>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
<h1>jQuery change class tutorial</h1>
<div class="example noClass">The first DIV element</div>
<div class="example noClass">The second DIV element</div>
<script>
$(".example")
.addClass("myClass otherClass")
.removeClass("example noClass");
</script>
</body>
Keep in mind that you don’t need to add any dot .
to the class names you want to add or remove. Some people unintentionally add dots before the class name as follows:
$(".example")
.addClass(".myClass .otherClass")
.removeClass(".example .noClass");
While the addClass()
method will work as intended, the removeClass()
method will fail to remove the classes, but you won’t get any error message.
Original article source at: https://sebhastian.com/
1668600738
Use setInterval() and clearInterval() methods in React class components
This tutorial will show you how to run the setInterval()
method as soon as your component is mounted (rendered) on the screen or when a button is clicked by the user.
This tutorial uses React class component for its code examples. For the function component equivalent, you can refer to this tutorial:
How to use setInterval() method inside React components
Let’s begin with starting the interval when the component is mounted.
To start the interval as soon as the class component has been rendered on the screen, you need to call the setInterval()
method inside the componentDidMount()
lifecycle method.
Here’s a pattern for using the setInterval()
method:
componentDidMount() {
setInterval(() => {
/*
Run any function or setState here
*/
}, 1000);
}
You can call the this.setState()
method inside the setInterval()
method to increment a previous state property value.
The following example uses the state property count
value as a timer that counts how many seconds have passed since the component has been rendered on the screen:
class App extends React.Component {
state = { count: 0 };
componentDidMount() {
const intervalId = setInterval(() => {
this.setState(prevState => {
return {
count: prevState.count + 1,
};
});
}, 1000);
}
componentWillUnmount(){
clearInterval(intervalId);
}
render() {
return (
<h1>The component has been rendered for {this.state.count} seconds</h1>
);
}
}
export default App;
The value of the count
property above will be incremented by 1 every 1000 milliseconds.
To stop the interval when the component is destroyed, you need to call the clearInterval()
method from inside the componentWillUnmount()
lifecycle method.
First, you need add a new property to the state object named intervalId
and set the initial value to 0
:
state = { count: 0, intervalId: 0 };
Next, save the interval ID returned from the setInterval()
method as the intervalId
state value.
The complete code for the componentDidMount()
method is as follows:
componentDidMount() {
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
Although it looks complicated, the additional code only calls the setState()
method to assign the newIntervalId
value as the state.intervalId
value.
The prevState
value is expanded on the new state returned from the setState()
method so that the count
property won’t be removed from the state itself.
And that’s how to clear the interval before unmounting the component. Now let’s see how you can start and stop the interval method from a button click.
To start the setInterval()
method when the user clicks on a button, you need to put the setInterval()
method call inside the button’s onClick
event handler property.
In essence, you only need to place the code inside the componentDidMount()
method above as the code you run when the button is clicked.
Take a look at the following code:
class App extends React.Component {
state = { count: 0, intervalId: 0 };
handleClick = () => {
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
render() {
return (
<div>
<h1>The component has been rendered for {this.state.count} seconds</h1>
<button onClick={this.handleClick}>Start counter</button>
</div>
);
}
}
export default App;
To stop the interval, you need to add an if
block inside the handleClick()
method above.
If the state.intervalId
value is not zero (truthy) then you need to do the following steps:
clearInterval()
method passing the state.intervalId
as its argumentsetState()
method and set the intervalId
value back to 0
handleClick()
method by using the return
statementHere’s the code implementing the above steps:
handleClick = () => {
if(this.state.intervalId){
clearInterval(this.state.intervalId);
this.setState(prevState => {
return {
...prevState,
intervalId: 0,
};
});
return;
}
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
Don’t forget to update the button’s label to Start counting
or Stop counting
depending on the state.intervalId
value:
<button onClick={this.handleClick}>
{this.state.intervalId? "Stop counter": "Start counter"}
</button>
The full code for the class component is as shown below:
class App extends React.Component {
state = { count: 0, intervalId: 0 };
handleClick = () => {
if(this.state.intervalId){
clearInterval(this.state.intervalId);
this.setState(prevState => {
return {
...prevState,
intervalId: 0,
};
});
return;
}
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
render() {
return (
<div>
<h1>The component has been rendered for {this.state.count} seconds</h1>
<button onClick={this.handleClick}>
{this.state.intervalId? "Stop counter": "Start counter"}
</button>
</div>
);
}
}
export default App;
And that’s how you can call the setInterval()
method with a button click inside a React class component.
Original article source at: https://sebhastian.com/
1668598942
Use setInterval() and clearInterval() methods in React class components
This tutorial will show you how to run the setInterval()
method as soon as your component is mounted (rendered) on the screen or when a button is clicked by the user.
This tutorial uses React class component for its code examples. For the function component equivalent, you can refer to this tutorial:
How to use setInterval() method inside React components
Let’s begin with starting the interval when the component is mounted.
To start the interval as soon as the class component has been rendered on the screen, you need to call the setInterval()
method inside the componentDidMount()
lifecycle method.
Here’s a pattern for using the setInterval()
method:
componentDidMount() {
setInterval(() => {
/*
Run any function or setState here
*/
}, 1000);
}
You can call the this.setState()
method inside the setInterval()
method to increment a previous state property value.
The following example uses the state property count
value as a timer that counts how many seconds have passed since the component has been rendered on the screen:
class App extends React.Component {
state = { count: 0 };
componentDidMount() {
const intervalId = setInterval(() => {
this.setState(prevState => {
return {
count: prevState.count + 1,
};
});
}, 1000);
}
componentWillUnmount(){
clearInterval(intervalId);
}
render() {
return (
<h1>The component has been rendered for {this.state.count} seconds</h1>
);
}
}
export default App;
The value of the count
property above will be incremented by 1 every 1000 milliseconds.
To stop the interval when the component is destroyed, you need to call the clearInterval()
method from inside the componentWillUnmount()
lifecycle method.
First, you need add a new property to the state object named intervalId
and set the initial value to 0
:
state = { count: 0, intervalId: 0 };
Next, save the interval ID returned from the setInterval()
method as the intervalId
state value.
The complete code for the componentDidMount()
method is as follows:
componentDidMount() {
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
Although it looks complicated, the additional code only calls the setState()
method to assign the newIntervalId
value as the state.intervalId
value.
The prevState
value is expanded on the new state returned from the setState()
method so that the count
property won’t be removed from the state itself.
And that’s how to clear the interval before unmounting the component. Now let’s see how you can start and stop the interval method from a button click.
To start the setInterval()
method when the user clicks on a button, you need to put the setInterval()
method call inside the button’s onClick
event handler property.
In essence, you only need to place the code inside the componentDidMount()
method above as the code you run when the button is clicked.
Take a look at the following code:
class App extends React.Component {
state = { count: 0, intervalId: 0 };
handleClick = () => {
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
render() {
return (
<div>
<h1>The component has been rendered for {this.state.count} seconds</h1>
<button onClick={this.handleClick}>Start counter</button>
</div>
);
}
}
export default App;
To stop the interval, you need to add an if
block inside the handleClick()
method above.
If the state.intervalId
value is not zero (truthy) then you need to do the following steps:
clearInterval()
method passing the state.intervalId
as its argumentsetState()
method and set the intervalId
value back to 0
handleClick()
method by using the return
statementHere’s the code implementing the above steps:
handleClick = () => {
if(this.state.intervalId){
clearInterval(this.state.intervalId);
this.setState(prevState => {
return {
...prevState,
intervalId: 0,
};
});
return;
}
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
Don’t forget to update the button’s label to Start counting
or Stop counting
depending on the state.intervalId
value:
<button onClick={this.handleClick}>
{this.state.intervalId? "Stop counter": "Start counter"}
</button>
The full code for the class component is as shown below:
class App extends React.Component {
state = { count: 0, intervalId: 0 };
handleClick = () => {
if(this.state.intervalId){
clearInterval(this.state.intervalId);
this.setState(prevState => {
return {
...prevState,
intervalId: 0,
};
});
return;
}
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
render() {
return (
<div>
<h1>The component has been rendered for {this.state.count} seconds</h1>
<button onClick={this.handleClick}>
{this.state.intervalId? "Stop counter": "Start counter"}
</button>
</div>
);
}
}
export default App;
And that’s how you can call the setInterval()
method with a button click inside a React class component.
Original article source at: https://sebhastian.com/setinterval-react-class/
1668576480
In this article, we'll look at the differences between Django's class-based views (CBV) and function-based views (FBV). We'll compare and contrast and dive into the pros and cons of each approach (along with Django's built-in generic class-based views). By the end, you should have a good understanding of when to use one over the other.
One of the main uses of Django (and essentially any other web framework) is to serve HTTP responses in response to HTTP requests. Django allows us to do that using so-called views. A view is just a callable that accepts a request and returns a response.
Django initially only supported function-based views (FBVs), but they were hard to extend, didn't take advantage of object-oriented programming (OOP) principles, and weren't DRY. This is why Django developers decided to add support for class-based views (CBVs). CBVs utilize OOP principles, which allow us to use inheritance, reuse code, and generally write better and cleaner code.
We need to keep in mind that CBVs are not designed to replace FBVs. Anything you can achieve with FBVs is also achievable with CBVs. They each have their own pros and cons.
Lastly, Django offers pre-made or generic CBVs which provide solutions to common problems. They have programmer-friendly names and offer solutions to problems like displaying data, editing data, and working with date-based data. They can be used on their own or inherited in custom views.
Let's look at the different view types and learn when it's appropriate to use which.
At their core, FBVs are just functions. They're easy to read and work with since you can see exactly what's happening. Due to their simplicity, they're a great fit for Django beginners. So, if you're just starting with Django, it's recommended to have some working knowledge of FBVs before diving into CBVs.
Pros
Cons
An example FBV looks like this:
from django.shortcuts import render, redirect
from django.views import View
def task_create_view(request):
if request.method == 'POST':
form = TaskForm(data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('task-list'))
return render(request, 'todo/task_create.html', {
'form': TaskForm(),
})
This view takes in a request
, performs some logic, and returns an HttpResponse
. Just by looking at the code, we can see the first downside: conditional branching. For each HTTP method, we have to create a separate branch. This can increase code complexity and lead to spaghetti code.
The next downside of FBVs is that they do not scale well. As your codebase grows bigger and bigger, you'll notice a lot of repeated (boilerplate) code for handling models (especially with CRUD operations). Try imagining how much a view for creating articles would differ from the example above... They'd be pretty much the same.
In order to use FBVs, we have to register them inside urls.py like so:
urlpatterns = [
path('create/', task_create_view, name='task-create'),
]
You should opt for FBVs when you're working on highly customized view logic. In other words, FBVs are a great use case for a view that doesn't share much code with other views. A few real-world examples for using FBVs would be: a statistics view, a chart view, and a password reset view.
Let's look at how a simple todo application that allows CRUD operations would be written using only FBVs.
Firstly, we'd initialize our project, define our models, create HTML templates and then start working on views.py. We'd probably end up with something like this:
# todo/views.py
from django.shortcuts import render, get_object_or_404, redirect
from .forms import TaskForm, ConfirmForm
from .models import Task
def task_list_view(request):
return render(request, 'todo/task_list.html', {
'tasks': Task.objects.all(),
})
def task_create_view(request):
if request.method == 'POST':
form = TaskForm(data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('task-list'))
return render(request, 'todo/task_create.html', {
'form': TaskForm(),
})
def task_detail_view(request, pk):
task = get_object_or_404(Task, pk=pk)
return render(request, 'todo/task_detail.html', {
'task': task,
})
def task_update_view(request, pk):
task = get_object_or_404(Task, pk=pk)
if request.method == 'POST':
form = TaskForm(instance=task, data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('task-detail', args={pk: pk}))
return render(request, 'todo/task_update.html', {
'task': task,
'form': TaskForm(instance=task),
})
def task_delete_view(request, pk):
task = get_object_or_404(Task, pk=pk)
if request.method == 'POST':
form = ConfirmForm(data=request.POST)
if form.is_valid():
task.delete()
return HttpResponseRedirect(reverse('task-list'))
return render(request, 'todo/task_delete.html', {
'task': task,
'form': ConfirmForm(),
})
You can get the full source code on GitHub.
We ended up with simple and straightforward view logic. You can't improve this code much.
Class-based views, which were introduced in Django 1.3, provide an alternative way to implement views as Python objects instead of functions. They allow us to use OOP principles (most importantly inheritance). We can use CBVs to generalize parts of our code and extract them as superclass views.
CBVs also allow you to use Django's built-in generic class-based views and mixins, which we'll take a look at in the next section.
Pros
Cons
For more, review What are the pros and cons of using class-based views in Django/Python?
Let's rewrite our previous FBV example as a CBV:
from django.shortcuts import render, redirect
from django.views import View
class TaskCreateView(View):
def get(self, request, *args, **kwargs):
return render(request, 'todo/task_create.html', {
'form': TaskForm(),
})
def post(self, request, *args, **kwargs):
form = TaskForm(data=request.POST)
if form.is_valid():
task = form.save()
return redirect('task-detail', pk=task.pk)
return self.get(request)
We can see that this example is not much different from the FBV approach. The logic is more or less the same. The main difference is code organization. Here each HTTP method is addressed with a separate method instead of conditional branching. In CBVs you can use the following methods: get
, post
, put
, patch
, delete
, head
, options
, trace
.
Another upside of this approach is that HTTP methods that are not defined automatically return a 405 Method Not Allowed
response.
When using FBVs, you can use one of the allowed HTTP method decorators, like
@require_http_methods
, to achieve the same thing.
Because Django's URL resolver expects a callable function, we need to call as_view() when registering them in urls.py:
urlpatterns = [
path('create/', TaskCreateView.as_view(), name='task-create'),
]
The code flow for CBVs is a little more complex because some stuff happens in the background. If we extend the base View class the following code steps will be executed:
HttpRequest
is routed to MyView
by the Django URL dispatcher.as_view()
on MyView
.as_view()
invokes setup()
and dispatch()
.dispatch()
triggers a method for a specific HTTP method or http_method_not_allowed()
.HttpResponse
is returned.Now, let's rewrite our todo application to only use CBVs:
# todo/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.views import View
from .forms import TaskForm, ConfirmForm
from .models import Task
class TaskListView(View):
def get(self, request, *args, **kwargs):
return render(request, 'todo/task_list.html', {
'tasks': Task.objects.all(),
})
class TaskCreateView(View):
def get(self, request, *args, **kwargs):
return render(request, 'todo/task_create.html', {
'form': TaskForm(),
})
def post(self, request, *args, **kwargs):
form = TaskForm(data=request.POST)
if form.is_valid():
task = form.save()
return redirect('task-detail', pk=task.pk)
return self.get(request)
class TaskDetailView(View):
def get(self, request, pk, *args, **kwargs):
task = get_object_or_404(Task, pk=pk)
return render(request, 'todo/task_detail.html', {
'task': task,
})
class TaskUpdateView(View):
def get(self, request, pk, *args, **kwargs):
task = get_object_or_404(Task, pk=pk)
return render(request, 'todo/task_update.html', {
'task': task,
'form': TaskForm(instance=task),
})
def post(self, request, pk, *args, **kwargs):
task = get_object_or_404(Task, pk=pk)
form = TaskForm(instance=task, data=request.POST)
if form.is_valid():
form.save()
return redirect('task-detail', pk=task.pk)
return self.get(request, pk)
class TaskDeleteView(View):
def get(self, request, pk, *args, **kwargs):
task = get_object_or_404(Task, pk=pk)
return render(request, 'todo/task_confirm_delete.html', {
'task': task,
'form': ConfirmForm(),
})
def post(self, request, pk, *args, **kwargs):
task = get_object_or_404(Task, pk=pk)
form = ConfirmForm(data=request.POST)
if form.is_valid():
task.delete()
return redirect('task-list')
return self.get(request, pk)
Also, let's not forget to make our urls.py call as_view()
:
# todo/urls.py
from django.urls import path
from .views import TaskListView, TaskDetailView, TaskCreateView, TaskUpdateView, TaskDeleteView
urlpatterns = [
path('', TaskListView.as_view(), name='task-list'),
path('create/', TaskCreateView.as_view(), name='task-create'),
path('<int:pk>/', TaskDetailView.as_view(), name='task-detail'),
path('update/<int:pk>/', TaskUpdateView.as_view(), name='task-update'),
path('delete/<int:pk>/', TaskDeleteView.as_view(), name='task-delete'),
]
You can get the full source code on GitHub.
We sacrificed a few lines of code for a bit cleaner code. We no longer use conditional branching. If we, for example, look at TaskCreateView
and TaskUpdateView
, we can see that they're pretty much the same. We could further improve this code by extracting the common logic into a parent class. Additionally, we could extract the view logic and use it for views for other models.
If you were to follow all of the refactoring suggestions mentioned in the previous section, you'd eventually be left with a view that mimics some of Django's generic class-based views. Django's generic CBVs are great for solving common problems like retrieving, creating, modifying, and deleting objects as well as pagination and archive views. They speed up the development process too.
Let's look at an example:
from django.views.generic import CreateView
class TaskCreateView(CreateView):
model = Task
context_object_name = 'task'
fields = ('name', 'description', 'is_done')
template_name = 'todo/task_create.html'
We created a class named TaskCreateView
and inherited CreateView
. By doing that we gained a lot of functionality, with almost no code. Now we just need to set the following attributes:
model
defines what Django model the view works with.fields
is used by Django to create a form (alternatively, we could provide form_class
).template_name
defines which template to use (defaults to /<app_name>/<model_name>_form.html
).context_object_name
defines the context key under which the model instance is passed to the template (defaults to object
).success_url
defines where the user gets redirected on success (alternatively, you can set get_absolute_url
in your model).For more information about generic CBVs, refer to the official documentation.
As you've probably guessed, there's a lot more magic happening behind the scenes with generic CBVs. They can be confusing even for experienced Django developers. Once you get the hang of them, though, you'll probably feel like a wizard.
You should use generic CBVs for views that perform common tasks (e.g., CRUD operations). If your view needs to do something that's not covered by CBVs, use mixins or a function-based view.
At the time of writing, Django comes with a decent amount of generic CBVs, which we can split into three categories:
Generic Display Views | Generic Editing Views | Generic Date-based Views |
---|---|---|
Designed to display data. | Provide a foundation for editing content. | Allow in-depth displaying of date-based data. |
We'll look at practical examples of how to use them here shortly.
Each generic view is made to solve one problem (e.g., display information, create/update something). If your view needs to do something more than that, you can create your view using mixins. Mixins are classes that offer discrete functionality and they can be combined to solve pretty much any problem.
You can also pick a generic CBV as a base and then include additional mixins.
Even Django's generic CBVs are composed of mixins. Let's look at CreateView
diagram:
We can see that it leverages a number of mixins, like ContextMixin
, SingleObjectMixin
, and FormMixin
. They have programmer-friendly names, so you should have a general idea of what each of them does based on their name.
Mixins take a lot of time to master and can oftentimes be confusing. If you're just starting with mixins I'd suggest you start by reading Using mixins with class-based views.
Now, let's rewrite the todo app for the final time using Django's generic class-based views:
# todo/views.py
from django.views.generic import ListView, DetailView, DeleteView, UpdateView, CreateView
class TaskListView(ListView):
model = Task
context_object_name = 'tasks'
class TaskCreateView(CreateView):
model = Task
context_object_name = 'task'
fields = ('name', 'description', 'is_done')
template_name = 'todo/task_create.html'
class TaskDetailView(DetailView):
model = Task
context_object_name = 'task'
class TaskUpdateView(UpdateView):
model = Task
context_object_name = 'task'
fields = ('name', 'description', 'is_done')
template_name = 'todo/task_update.html'
class TaskDeleteView(DeleteView):
model = Task
context_object_name = 'task'
success_url = '/'
You can get the full source code on GitHub.
By using Django generic CBVs, we split our code in half. Further, the code is much cleaner and easier to maintain, but it can be much harder to read and understand if you're new to generic CBVs.
One view type is not better than the other. It all depends on the situation and personal preferences. Sometimes FBVs are better and other times CBVs are better. Try to remember their pros and cons to make a good decision when writing a specific view. If you're still not exactly sure when to use which, you can practice a bit by converting FBVs to CBVs and vice versa. Additionally, you can use this flowchart:
I personally prefer FBVs for smaller projects (that cannot be solved with generic CBVs) and opt for CBVs when dealing with larger codebases.
Original article source at: https://testdriven.io/
1668493276
PHP provides you with the final
keyword that you can use as a modifier for classes and functions.
When you add the final
keyword to a class, that class can’t be extended.
Here’s an example of creating a final class:
<?php
final class Car {
function start(){
print "Start the engine";
}
}
PHP will throw an error when you try to extend a final class as shown below:
class Tesla extends Car {}
// Fatal error:
// Class Tesla cannot extend final class Car
The final
keyword is useful to restrict a class
, removing the possibility of extending that class.
You can also put the final
keyword in front of class functions to disable child classes from overriding that function:
<?php
class Car {
final function start(){
print "Start the engine";
}
}
class Tesla extends Car {
// 👇 Cannot override final method Car::start()
function start(){
print "Tesla starting...";
}
}
Now you’ve learned how to create a final class in PHP.
Original article source at: https://sebhastian.com/
1667861760
Its ES6 and Typescript era. Nowadays you are working with classes and constructor objects more than ever. Class-transformer allows you to transform plain object to some instance of class and versa. Also it allows to serialize / deserialize object based on criteria. This tool is super useful on both frontend and backend.
Example how to use with angular 2 in plunker. Source code is available here.
In JavaScript there are two types of objects:
Plain objects are objects that are instances of Object
class. Sometimes they are called literal objects, when created via {}
notation. Class objects are instances of classes with own defined constructor, properties and methods. Usually you define them via class
notation.
So, what is the problem?
Sometimes you want to transform plain javascript object to the ES6 classes you have. For example, if you are loading a json from your backend, some api or from a json file, and after you JSON.parse
it you have a plain javascript object, not instance of class you have.
For example you have a list of users in your users.json
that you are loading:
[
{
"id": 1,
"firstName": "Johny",
"lastName": "Cage",
"age": 27
},
{
"id": 2,
"firstName": "Ismoil",
"lastName": "Somoni",
"age": 50
},
{
"id": 3,
"firstName": "Luke",
"lastName": "Dacascos",
"age": 12
}
]
And you have a User
class:
export class User {
id: number;
firstName: string;
lastName: string;
age: number;
getName() {
return this.firstName + ' ' + this.lastName;
}
isAdult() {
return this.age > 36 && this.age < 60;
}
}
You are assuming that you are downloading users of type User
from users.json
file and may want to write following code:
fetch('users.json').then((users: User[]) => {
// you can use users here, and type hinting also will be available to you,
// but users are not actually instances of User class
// this means that you can't use methods of User class
});
In this code you can use users[0].id
, you can also use users[0].firstName
and users[0].lastName
. However you cannot use users[0].getName()
or users[0].isAdult()
because "users" actually is array of plain javascript objects, not instances of User object. You actually lied to compiler when you said that its users: User[]
.
So what to do? How to make a users
array of instances of User
objects instead of plain javascript objects? Solution is to create new instances of User object and manually copy all properties to new objects. But things may go wrong very fast once you have a more complex object hierarchy.
Alternatives? Yes, you can use class-transformer. Purpose of this library is to help you to map your plain javascript objects to the instances of classes you have.
This library also great for models exposed in your APIs, because it provides a great tooling to control what your models are exposing in your API. Here is an example how it will look like:
fetch('users.json').then((users: Object[]) => {
const realUsers = plainToClass(User, users);
// now each user in realUsers is an instance of User class
});
Now you can use users[0].getName()
and users[0].isAdult()
methods.
Install module:
npm install class-transformer --save
reflect-metadata
shim is required, install it too:
npm install reflect-metadata --save
and make sure to import it in a global place, like app.ts:
import 'reflect-metadata';
ES6 features are used, if you are using old version of node.js you may need to install es6-shim:
npm install es6-shim --save
and import it in a global place like app.ts:
import 'es6-shim';
Install module:
npm install class-transformer --save
reflect-metadata
shim is required, install it too:
npm install reflect-metadata --save
add <script>
to reflect-metadata in the head of your index.html
:
<html>
<head>
<!-- ... -->
<script src="node_modules/reflect-metadata/Reflect.js"></script>
</head>
<!-- ... -->
</html>
If you are using angular 2 you should already have this shim installed.
If you are using system.js you may want to add this into map
and package
config:
{
"map": {
"class-transformer": "node_modules/class-transformer"
},
"packages": {
"class-transformer": { "main": "index.js", "defaultExtension": "js" }
}
}
This method transforms a plain javascript object to instance of specific class.
import { plainToClass } from 'class-transformer';
let users = plainToClass(User, userJson); // to convert user plain object a single user. also supports arrays
This method transforms a plain object into an instance using an already filled Object which is an instance of the target class.
const defaultUser = new User();
defaultUser.role = 'user';
let mixedUser = plainToClassFromExist(defaultUser, user); // mixed user should have the value role = user when no value is set otherwise.
This method transforms your class object back to plain javascript object, that can be JSON.stringify
later.
import { classToPlain } from 'class-transformer';
let photo = classToPlain(photo);
This method transforms your class object into a new instance of the class object. This may be treated as deep clone of your objects.
import { classToClass } from 'class-transformer';
let photo = classToClass(photo);
You can also use an ignoreDecorators
option in transformation options to ignore all decorators you classes is using.
You can serialize your model right to json using serialize
method:
import { serialize } from 'class-transformer';
let photo = serialize(photo);
serialize
works with both arrays and non-arrays.
You can deserialize your model from json using the deserialize
method:
import { deserialize } from 'class-transformer';
let photo = deserialize(Photo, photo);
To make deserialization work with arrays, use the deserializeArray
method:
import { deserializeArray } from 'class-transformer';
let photos = deserializeArray(Photo, photos);
The default behaviour of the plainToClass
method is to set all properties from the plain object, even those which are not specified in the class.
import { plainToClass } from 'class-transformer';
class User {
id: number;
firstName: string;
lastName: string;
}
const fromPlainUser = {
unkownProp: 'hello there',
firstName: 'Umed',
lastName: 'Khudoiberdiev',
};
console.log(plainToClass(User, fromPlainUser));
// User {
// unkownProp: 'hello there',
// firstName: 'Umed',
// lastName: 'Khudoiberdiev',
// }
If this behaviour does not suit your needs, you can use the excludeExtraneousValues
option in the plainToClass
method while exposing all your class properties as a requirement.
import { Expose, plainToClass } from 'class-transformer';
class User {
@Expose() id: number;
@Expose() firstName: string;
@Expose() lastName: string;
}
const fromPlainUser = {
unkownProp: 'hello there',
firstName: 'Umed',
lastName: 'Khudoiberdiev',
};
console.log(plainToClass(User, fromPlainUser, { excludeExtraneousValues: true }));
// User {
// id: undefined,
// firstName: 'Umed',
// lastName: 'Khudoiberdiev'
// }
When you are trying to transform objects that have nested objects, it's required to known what type of object you are trying to transform. Since Typescript does not have good reflection abilities yet, we should implicitly specify what type of object each property contain. This is done using @Type
decorator.
Lets say we have an album with photos. And we are trying to convert album plain object to class object:
import { Type, plainToClass } from 'class-transformer';
export class Album {
id: number;
name: string;
@Type(() => Photo)
photos: Photo[];
}
export class Photo {
id: number;
filename: string;
}
let album = plainToClass(Album, albumJson);
// now album is Album object with Photo objects inside
In case the nested object can be of different types, you can provide an additional options object, that specifies a discriminator. The discriminator option must define a property
that holds the subtype name for the object and the possible subTypes
that the nested object can converted to. A sub type has a value
, that holds the constructor of the Type and the name
, that can match with the property
of the discriminator.
Lets say we have an album that has a top photo. But this photo can be of certain different types. And we are trying to convert album plain object to class object. The plain object input has to define the additional property __type
. This property is removed during transformation by default:
JSON input:
{
"id": 1,
"name": "foo",
"topPhoto": {
"id": 9,
"filename": "cool_wale.jpg",
"depth": 1245,
"__type": "underwater"
}
}
import { Type, plainToClass } from 'class-transformer';
export abstract class Photo {
id: number;
filename: string;
}
export class Landscape extends Photo {
panorama: boolean;
}
export class Portrait extends Photo {
person: Person;
}
export class UnderWater extends Photo {
depth: number;
}
export class Album {
id: number;
name: string;
@Type(() => Photo, {
discriminator: {
property: '__type',
subTypes: [
{ value: Landscape, name: 'landscape' },
{ value: Portrait, name: 'portrait' },
{ value: UnderWater, name: 'underwater' },
],
},
})
topPhoto: Landscape | Portrait | UnderWater;
}
let album = plainToClass(Album, albumJson);
// now album is Album object with a UnderWater object without `__type` property.
Hint: The same applies for arrays with different sub types. Moreover you can specify keepDiscriminatorProperty: true
in the options to keep the discriminator property also inside your resulting class.
You can expose what your getter or method return by setting an @Expose()
decorator to those getters or methods:
import { Expose } from 'class-transformer';
export class User {
id: number;
firstName: string;
lastName: string;
password: string;
@Expose()
get name() {
return this.firstName + ' ' + this.lastName;
}
@Expose()
getFullName() {
return this.firstName + ' ' + this.lastName;
}
}
If you want to expose some of the properties with a different name, you can do that by specifying a name
option to @Expose
decorator:
import { Expose } from 'class-transformer';
export class User {
@Expose({ name: 'uid' })
id: number;
firstName: string;
lastName: string;
@Expose({ name: 'secretKey' })
password: string;
@Expose({ name: 'fullName' })
getFullName() {
return this.firstName + ' ' + this.lastName;
}
}
Sometimes you want to skip some properties during transformation. This can be done using @Exclude
decorator:
import { Exclude } from 'class-transformer';
export class User {
id: number;
email: string;
@Exclude()
password: string;
}
Now when you transform a User, the password
property will be skipped and not be included in the transformed result.
You can control on what operation you will exclude a property. Use toClassOnly
or toPlainOnly
options:
import { Exclude } from 'class-transformer';
export class User {
id: number;
email: string;
@Exclude({ toPlainOnly: true })
password: string;
}
Now password
property will be excluded only during classToPlain
operation. Vice versa, use the toClassOnly
option.
You can skip all properties of the class, and expose only those are needed explicitly:
import { Exclude, Expose } from 'class-transformer';
@Exclude()
export class User {
@Expose()
id: number;
@Expose()
email: string;
password: string;
}
Now id
and email
will be exposed, and password will be excluded during transformation. Alternatively, you can set exclusion strategy during transformation:
import { classToPlain } from 'class-transformer';
let photo = classToPlain(photo, { strategy: 'excludeAll' });
In this case you don't need to @Exclude()
a whole class.
If you name your private properties with a prefix, lets say with _
, then you can exclude such properties from transformation too:
import { classToPlain } from 'class-transformer';
let photo = classToPlain(photo, { excludePrefixes: ['_'] });
This will skip all properties that start with _
prefix. You can pass any number of prefixes and all properties that begin with these prefixes will be ignored. For example:
import { Expose, classToPlain } from 'class-transformer';
export class User {
id: number;
private _firstName: string;
private _lastName: string;
_password: string;
setName(firstName: string, lastName: string) {
this._firstName = firstName;
this._lastName = lastName;
}
@Expose()
get name() {
return this._firstName + ' ' + this._lastName;
}
}
const user = new User();
user.id = 1;
user.setName('Johny', 'Cage');
user._password = '123';
const plainUser = classToPlain(user, { excludePrefixes: ['_'] });
// here plainUser will be equal to
// { id: 1, name: "Johny Cage" }
You can use groups to control what data will be exposed and what will not be:
import { Exclude, Expose, classToPlain } from 'class-transformer';
export class User {
id: number;
name: string;
@Expose({ groups: ['user', 'admin'] }) // this means that this data will be exposed only to users and admins
email: string;
@Expose({ groups: ['user'] }) // this means that this data will be exposed only to users
password: string;
}
let user1 = classToPlain(user, { groups: ['user'] }); // will contain id, name, email and password
let user2 = classToPlain(user, { groups: ['admin'] }); // will contain id, name and email
If you are building an API that has different versions, class-transformer has extremely useful tools for that. You can control which properties of your model should be exposed or excluded in what version. Example:
import { Exclude, Expose, classToPlain } from 'class-transformer';
export class User {
id: number;
name: string;
@Expose({ since: 0.7, until: 1 }) // this means that this property will be exposed for version starting from 0.7 until 1
email: string;
@Expose({ since: 2.1 }) // this means that this property will be exposed for version starting from 2.1
password: string;
}
let user1 = classToPlain(user, { version: 0.5 }); // will contain id and name
let user2 = classToPlain(user, { version: 0.7 }); // will contain id, name and email
let user3 = classToPlain(user, { version: 1 }); // will contain id and name
let user4 = classToPlain(user, { version: 2 }); // will contain id and name
let user5 = classToPlain(user, { version: 2.1 }); // will contain id, name and password
Sometimes you have a Date in your plain javascript object received in a string format. And you want to create a real javascript Date object from it. You can do it simply by passing a Date object to the @Type
decorator:
import { Type } from 'class-transformer';
export class User {
id: number;
email: string;
password: string;
@Type(() => Date)
registrationDate: Date;
}
Same technique can be used with Number
, String
, Boolean
primitive types when you want to convert your values into these types.
When you are using arrays you must provide a type of the object that array contains. This type, you specify in a @Type()
decorator:
import { Type } from 'class-transformer';
export class Photo {
id: number;
name: string;
@Type(() => Album)
albums: Album[];
}
You can also use custom array types:
import { Type } from 'class-transformer';
export class AlbumCollection extends Array<Album> {
// custom array functions ...
}
export class Photo {
id: number;
name: string;
@Type(() => Album)
albums: AlbumCollection;
}
Library will handle proper transformation automatically.
ES6 collections Set
and Map
also require the @Type
decorator:
export class Skill {
name: string;
}
export class Weapon {
name: string;
range: number;
}
export class Player {
name: string;
@Type(() => Skill)
skills: Set<Skill>;
@Type(() => Weapon)
weapons: Map<string, Weapon>;
}
You can perform additional data transformation using @Transform
decorator. For example, you want to make your Date
object to be a moment
object when you are transforming object from plain to class:
import { Transform } from 'class-transformer';
import * as moment from 'moment';
import { Moment } from 'moment';
export class Photo {
id: number;
@Type(() => Date)
@Transform(({ value }) => moment(value), { toClassOnly: true })
date: Moment;
}
Now when you call plainToClass
and send a plain representation of the Photo object, it will convert a date value in your photo object to moment date. @Transform
decorator also supports groups and versioning.
The @Transform
decorator is given more arguments to let you configure how you want the transformation to be done.
@Transform(({ value, key, obj, type }) => value)
Argument | Description |
---|---|
value | The property value before the transformation. |
key | The name of the transformed property. |
obj | The transformation source object. |
type | The transformation type. |
options | The options object passed to the transformation method. |
Signature | Example | Description |
---|---|---|
@TransformClassToPlain | @TransformClassToPlain({ groups: ["user"] }) | Transform the method return with classToPlain and expose the properties on the class. |
@TransformClassToClass | @TransformClassToClass({ groups: ["user"] }) | Transform the method return with classToClass and expose the properties on the class. |
@TransformPlainToClass | @TransformPlainToClass(User, { groups: ["user"] }) | Transform the method return with plainToClass and expose the properties on the class. |
The above decorators accept one optional argument: ClassTransformOptions - The transform options like groups, version, name
An example:
@Exclude()
class User {
id: number;
@Expose()
firstName: string;
@Expose()
lastName: string;
@Expose({ groups: ['user.email'] })
email: string;
password: string;
}
class UserController {
@TransformClassToPlain({ groups: ['user.email'] })
getUser() {
const user = new User();
user.firstName = 'Snir';
user.lastName = 'Segal';
user.password = 'imnosuperman';
return user;
}
}
const controller = new UserController();
const user = controller.getUser();
the user
variable will contain only firstName,lastName, email properties because they are the exposed variables. email property is also exposed because we metioned the group "user.email".
Generics are not supported because TypeScript does not have good reflection abilities yet. Once TypeScript team provide us better runtime type reflection tools, generics will be implemented. There are some tweaks however you can use, that maybe can solve your problem. Checkout this example.
NOTE If you use class-validator together with class-transformer you propably DON'T want to enable this function.
Enables automatic conversion between built-in types based on type information provided by Typescript. Disabled by default.
import { IsString } from 'class-validator';
class MyPayload {
@IsString()
prop: string;
}
const result1 = plainToClass(MyPayload, { prop: 1234 }, { enableImplicitConversion: true });
const result2 = plainToClass(MyPayload, { prop: 1234 }, { enableImplicitConversion: false });
/**
* result1 will be `{ prop: "1234" }` - notice how the prop value has been converted to string.
* result2 will be `{ prop: 1234 }` - default behaviour
*/
Circular references are ignored. For example, if you are transforming class User
that contains property photos
with type of Photo
, and Photo
contains link user
to its parent User
, then user
will be ignored during transformation. Circular references are not ignored only during classToClass
operation.
Lets say you want to download users and want them automatically to be mapped to the instances of User
class.
import { plainToClass } from 'class-transformer';
this.http
.get('users.json')
.map(res => res.json())
.map(res => plainToClass(User, res as Object[]))
.subscribe(users => {
// now "users" is type of User[] and each user has getName() and isAdult() methods available
console.log(users);
});
You can also inject a class ClassTransformer
as a service in providers
, and use its methods.
Example how to use with angular 2 in plunker. Source code is here.
Take a look on samples in ./sample for more examples of usages.
See information about breaking changes and release notes here.
Author: Typestack
Source Code: https://github.com/typestack/class-transformer
License: MIT license