SVG Tutorial

posted on June 12, 2021

tags:

What is SVG?

  • SVG, Scalable Vector Graphics is an XML based language to define vector based graphics.

  • SVG is intended to display images over the web.

  • Being vector images, SVG image never loses quality no matter how they are zoomed out or resized.

  • SVG images supports interactivity and animation.

  • SVG is a W3C standard.

  • Others image formats like raster images can also be clubbed with SVG images.

  • SVG integrates well with XSLT and DOM of HTML.

Advantages

  • Use any text editor to create and edit SVG images.

  • Being XML based, SVG images are searchable, indexable and can be scripted and compressed.

  • SVG images are highly scalable as they never loses quality no matter how they are zoomed out or resized

  • Good printing quality at any resolution

  • SVG is an Open Standard

Disadvantages

  • Being text format size is larger then compared to binary formatted raster images.

  • Size can be big even for small image.

Example

Following XML snippet can be used to draw a circle in web browser.

<svg width="100" height="100">
   <circle cx="50" cy="50" r="40" stroke="red" stroke-width="2" fill="green" />
</svg>

Embed the SVG XML directly in an HTML page.

testSVG.htm

<html>
   <title>SVG Image</title>
   <body>
   
      <h1>Sample SVG Image</h1>
      
      <svg width="100" height="100">
         <circle cx="50" cy="50" r="40" stroke="red" stroke-width="2" fill="green" />
      </svg>
   
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. In Internet Explorer, activeX controls are required to view SVG images.

How SVG integrates with HTML

  • <svg> element indicates the start of SVG image.

  • <svg> element's width and height attributes defines the height and width of the SVG image.

  • In above example, we've used a <circle> element to draw a circle.

  • cx and cy attribute represents center of the circle. Default value is (0,0). r attribute represents radius of circle.

  • Other attributes stroke and stroke-width controls the outlining of the circle.

  • fill attribute defines the fill color of the circle.

  • Closing</svg> tag indicates the end of SVG image.

SVG - Shapes

SVG provides number of shapes which can be used to draw images. Following are the common shapes.

Sr.No. Shape Type & Description
1 rect

Used to draw a rectangle.

2 circle

Used to draw a circle.

3 ellipse

Used to draw a ellipse.

4 line

Used to draw a line.

5 polygon

Used to draw a closed shape consisting of connected straight lines.

6 polyline

Used to draw a open shape consisting of connected straight lines.

7 path

Used to draw any path.

SVG - Text

<text> element is used to draw text.

Declaration

Following is the syntax declaration of <text> element. We've shown main attributes only.

<text
  x="x-cordinates"
  y="y-cordinates"
  
  dx="list of lengths"
  dy="list of lengths"
  
  rotate="list of numbers"
  textlength="length"
  lengthAdjust="spacing" >
</text>

Attributes

Sr.No. Attribute & Description
1 x − x axis coordinates of glyphs.
2 y − y axis coordinates of glyphs.
3 dx − shift along with x-axis.
4 dy − shift along with y-axis.
5 rotate − rotation applied to all glyphs.
6 textlength − rendering length of the text.
7 lengthAdjust − type of adjustment with the rendered length of the text.

Example

testSVG.htm

<html>
   <title>SVG Text</title>
   <body>
      
      <h1>Sample SVG Text</h1>
      
      <svg width="800" height="800">
         <g>
            <text x="30" y="12" >Text: </text>
            <text x="30" y="30" fill="rgb(121,0,121)">WWW.YourSite.COM</text>
         </g> 
      </svg>
   
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

Text with rotate

<html>
   <title>SVG Text</title>
   <body>
      <h1>Sample SVG Text</h1>
      
      <svg width="800" height="800">
         <g>
            <text x="30" y="12" >Multiline Text: </text>
            <text x="30" y="30" fill="rgb(121,0,121)">WWW.yoursite.COM
            <tspan x="30" y="50" font-weight="bold">Simply Easy learning.</tspan>
            <tspan x="30" y="70">We teach just for free.</tspan>
            </text>
         </g>
      </svg>
      
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

Multiline Text

<html>
   <title>SVG Text</title>
   <body>
      <h1>Sample SVG Text</h1>
      
      <svg width="570" height="100">
         <g>
            <text x="30" y="12" >Multiline Text: </text>
            <text x="30" y="30" fill="rgb(121,0,121)">WWW.yoursite.COM
               <tspan x="30" y="50" font-weight="bold">Simply Easy learning.</tspan>
               <tspan x="30" y="70">We teach just for free.</tspan>
            </text>
         </g>
      </svg>
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

Hyper link Text

<html>
   <title>SVG Text</title>
   <body>
      <h1>Sample SVG Text</h1>
      
      <svg width="800" height="800">
         <g>
            <text x="30" y="10" >Text as Link: </text>
         
            <a xlink:href="http://www.yoursite.com/svg/" target="_blank">
               <text font-family="Verdana" font-size="20"  x="30" y="30" 
               fill="rgb(121,0,121)">WWW.yoursite.COM</text>
            </a>
         </g>
      </svg>
      
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

SVG - Stroke

SVG supports multiple stroke properties.

Following are the main stroke properties used.

Sr.No. Stroke Type & Description
1 stroke − defines color of text, line or outline of any element.
2 stroke-width − defines thickness of text, line or outline of any element.
3 stroke-linecap − defines different types of ending of a line or outline of any path.
4 stroke-dasharray − used to create dashed lines.

Example

testSVG.htm

<html>
   <title>SVG Stroke</title>
   <body>
   
      <h1>Sample SVG Stroke</h1>
      
      <svg width="800" height="800">
         <g>
            <text x="30" y="30" >Using stroke: </text>
            <path stroke="red" d="M 50 50 L 300 50" />
            <path stroke="green" d="M 50 70 L 300 70" />
            <path stroke="blue" d="M 50 90 L 300 90" />
         </g> 
      </svg>
   
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

Stroke width

<html>
   <title>SVG Stroke</title>
   <body>
      
      <h1>Sample SVG Stroke</h1>
      
      <svg width="800" height="800">
         <text x="30" y="10" >Using stroke-width: </text>
         <path stroke-width="2" stroke="black" d="M 50 50 L 300 50" />
         <path stroke-width="4" stroke="black" d="M 50 70 L 300 70" />
         <path stroke-width="6" stroke="black" d="M 50 90 L 300 90" />
      </svg>
      
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

stroke-linecap

<html>
   <title>SVG Stroke</title>
   <body>
      
      <h1>Sample SVG Stroke</h1>
      
      <svg width="800" height="800">
         <g>
            <text x="30" y="30" >Using stroke-linecap: </text>
         
            <path stroke-linecap="butt" stroke-width="6" 
            stroke="black" d="M 50 50 L 300 50" />
         
            <path stroke-linecap="round" stroke-width="6" 
            stroke="black" d="M 50 70 L 300 70" />
         
            <path stroke-linecap="square" stroke-width="6"
            stroke="black" d="M 50 90 L 300 90" />
         </g>
      </svg>
   
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

stroke-dasharray

<html>
   <title>SVG Stroke</title>
   <body>
   
      <h1>Sample SVG Stroke</h1>
      
      <svg width="800" height="800">
         <g>
            <text x="30" y="30" >Using stroke-dasharray: </text>
            
            <path stroke-dasharray="5,5" stroke-width="6" 
            stroke="black" d="M 50 50 L 300 50" />
            
            <path stroke-dasharray="10,10" stroke-width="6" 
            stroke="black" d="M 50 70 L 300 70" />
            
            <path stroke-dasharray="20,10,5,5,5,10" stroke-width="6" 
            stroke="black" d="M 50 90 L 300 90" />
         </g>
      </svg>
   
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

SVG - Filters

SVG uses <filter> element to define filters. <filter> element uses an id attribute to uniquely identify it.Filters are defined within <def> elements and then are referenced by graphics elements by their ids.

SVG provides a rich set of filters. Following is the list of the commonly used filters.

  • feBlend
  • feColorMatrix
  • feComponentTransfer
  • feComposite
  • feConvolveMatrix
  • feDiffuseLighting
  • feDisplacementMap
  • feFlood
  • feGaussianBlur
  • feImage
  • feMerge
  • feMorphology
  • feOffset - filter for drop shadows
  • feSpecularLighting
  • feTile
  • feTurbulence
  • feDistantLight
  • fePointLight
  • feSpotLight

Declaration

Following is the syntax declaration of <filter> element. We've shown main attributes only.

<filter
   filterUnits="units to define filter effect region"
   primitiveUnits="units to define primitive filter subregion"
   
   x="x-axis co-ordinate" 
   y="y-axis co-ordinate"     
   
   width="length"
   height="length"
   
   filterRes="numbers for filter region"
   xlink:href="reference to another filter" >
</filter>

Attributes

Sr.No. Name & Description
1 filterUnits − units to define filter effect region. It specifies the coordinate system for the various length values within the filter and for the attributes defining the filter subregion. If filterUnits="userSpaceOnUse", values represent values in the current user coordinate system in place at the time when the 'filter' element is used. If filterUnits="objectBoundingBox", values represent values in fractions or percentages of the bounding box on the referencing element in place at the time when the 'filter' element is used. Default is userSpaceOnUse.
2 primitiveUnits − units to define filter effect region. It specifies the coordinate system for the various length values within the filter and for the attributes defining the filter subregion. If filterUnits="userSpaceOnUse", values represent values in the current user coordinate system in place at the time when the 'filter' element is used. If filterUnits="objectBoundingBox", values represent values in fractions or percentages of the bounding box on the referencing element in place at the time when the 'filter' element is used. Default is userSpaceOnUse.
3 x − x-axis co-ordinate of the filter bounding box. Defeault is 0.
4 y − y-axis co-ordinate of the filter bounding box. Default is 0.
5 width − width of the filter bounding box. Default is 0.
6 height − height of the filter bounding box. Default is 0.
7 filterRes − numbers representing filter regions.
8 xlink:href − used to refer to another filter.

Example

testSVG.htm

<html>
   <title>SVG Filter</title>
   <body>
   
      <h1>Sample SVG Filter</h1>
   
      <svg width="800" height="800">
      
         <defs>
            <filter id="filter1" x="0" y="0">
               <feGaussianBlur in="SourceGraphic" stdDeviation="8" />
            </filter>
            
            <filter id="filter2" x="0" y="0" width="200%" height="200%">
               <feOffset result="offOut" in="SourceAlpha" dx="20" dy="20" />
               <feGaussianBlur result="blurOut" in="offOut" stdDeviation="10" />
               <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
            </filter>
         </defs>
         
         <g>
            <text x="30" y="50" >Using Filters (Blur Effect): </text>
            <rect x="100" y="100" width="90" height="90" stroke="green" stroke-width="3"
            fill="green" filter="url(#filter1)" />      
         </g> 
         
      </svg>
   
   </body>
</html>
  • Two <filter> elements defined as filter1 and filter2.

  • feGaussianBlur filter effect defines the blur effect with the amount of blur using stdDeviation.

  • in="SourceGraphic" defines that the effect is applicable for the entire element.

  • feOffset filter effect is used to create shadow effect. in="SourceAlpha" defines that the effect is applicable for the alpha part of RGBA graphics.

  • <rect> elements linked the filters using filter attribute.

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

Filter with Shadow effect

<html>
   <title>SVG Filter</title>
   <body>
      
      <h1>Sample SVG Filter</h1>
      
      <svg width="800" height="800">
      
         <defs>
            <filter id="filter1" x="0" y="0">
               <feGaussianBlur in="SourceGraphic" stdDeviation="8" />
            </filter>
            
            <filter id="filter2" x="0" y="0" width="200%" height="200%">
               <feOffset result="offOut" in="SourceAlpha" dx="20" dy="20" />
               <feGaussianBlur result="blurOut" in="offOut" stdDeviation="10" />
               <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
            </filter>
         </defs>
         
         <g>
            <text x="30" y="50" >Using Filters (Shadow Effect): </text>
            <rect x="100" y="100" width="90" height="90" stroke="green" stroke-width="3"
            fill="green" filter="url(#filter2)" />
         </g>
         
      </svg>
   
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

SVG - Patterns

SVG uses <pattern> element to define patterns. Patterns are defined using <pattern> element and are used to fill graphics elements in tiled fashion.

Declaration

Following is the syntax declaration of <pattern> element. We've shown main attributes only.

<pattern
   patternUnits="units to define x,y, width and height attributes."
   patternContentUnits ="units to define co-ordinate system of contents of pattern"
   patternTransform = "definition of an additional transformation from the pattern coordinate system onto the target coordinate system"
   
   x="x-axis co-ordinate" 
   y="y-axis co-ordinate"     
   
   width="length"
   height="length"
   
   preserveAspectRatio="to preserve width/height ratio of original content"
   xlink:href="reference to another pattern" >
</pattern>

Attributes

Sr.No. Name & Description
1 patternUnits − units to define patterns effect region. It specifies the coordinate system for the various length values within the pattern and for the attributes defining the pattern subregion. If patternUnits="userSpaceOnUse", values represent values in the current user coordinate system in place at the time when the 'pattern' element is used. If patternUnits="objectBoundingBox", values represent values in fractions or percentages of the bounding box on the referencing element in place at the time when the 'pattern' element is used. Default is userSpaceOnUse.
2 patternContentUnits − units to define pattern content region. It specifies the coordinate system for the various length values within the pattern and for the attributes defining the pattern subregion. If patternContentUnits="userSpaceOnUse", values represent values in the current user coordinate system in place at the time when the 'pattern' element is used. If patternContentUnits="objectBoundingBox", values represent values in fractions or percentages of the bounding box on the referencing element in place at the time when the 'pattern' element is used. Default is userSpaceOnUse.
3 x − x-axis co-ordinate of the pattern bounding box. Defeault is 0.
4 y − y-axis co-ordinate of the pattern bounding box. Default is 0.
5 width − width of the pattern bounding box. Default is 0.
6 height − height of the pattern bounding box. Default is 0.
7 preserveAspectRatio - to preserve width/height ratio of original content.
8 xlink:href − used to refer to another pattern.

Example

testSVG.htm

<html>
   <title>SVG Pattern</title>
   <body>
      <h1>Sample SVG Pattern</h1>
      
      <svg width="800" height="800">
         
         <defs>
            <pattern id="pattern1" patternUnits="userSpaceOnUse"
               x="0" y="0" width="100" height="100"
               viewBox="0 0 4 4" >
               <path d="M 0 0 L 3 0 L 1.5 3 z" fill="blue" stroke="green" />
            </pattern> 
         </defs>
         
         <g>
            <text x="30" y="50" >Using Pattern (Triangles): </text>
            <rect x="100" y="100" width="300" height="300" stroke="green" 
            stroke-width="3" fill="url(#pattern1)" />
         </g> 
         
      </svg>
   
   </body>
</html>
  • One <pattern> element defined as pattern1.

  • In pattern, a viewbox is defined and a path which is to be used as pattern is defined.

  • in rect element, in fill attribute, url of the pattern is specified to fill the rectangle with pattern created earlier.

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

SVG - Gradients

Gradient refers to smooth transition of one color to another color within a shape. SVG provides two types of gradients.

  • Linear Gradients − Represents linear transition of one color to another from one direction to another.

  • Radial Gradients − Represents circular transition of one color to another from one direction to another.

Linear Gradients

Declaration

Following is the syntax declaration of <linearGradient> element. We've shown main attributes only.

<linearGradient
   gradientUnits ="units to define co-ordinate system of contents of gradient"
   gradientTransform = "definition of an additional transformation from the gradient coordinate system onto the target coordinate system"
   
   x1="x-axis co-ordinate" 
   y1="y-axis co-ordinate"     
   x2="x-axis co-ordinate" 
   y2="y-axis co-ordinate"     
   
   spreadMethod="indicates method of spreading the gradient within graphics element"
   xlink:href="reference to another gradient" >
</linearGradient>

Attributes

Sr.No. Name & Description
1 gradientUnits − units to define the coordinate system for the various length values within the gradient. If gradientUnits="userSpaceOnUse", values represent values in the current user coordinate system in place at the time when the gradient element is used. If patternContentUnits="objectBoundingBox", values represent values in fractions or percentages of the bounding box on the referencing element in place at the time when the gradient element is used. Default is userSpaceOnUse.
2 x1 − x-axis co-ordinate of the gradient vector. Defeault is 0.
3 y1 − y-axis co-ordinate of the gradient vector. Default is 0.
4 x2 − x-axis co-ordinate of the gradient vector. Defeault is 0.
5 y2 − y-axis co-ordinate of the gradient vector. Default is 0.
6 spreadMethod − indicates method of spreading the gradient within graphics element. Default is 'pad'.
7 xlink:href − used to refer to another gradient.

Example

testSVG.htm

<html>
   <title>SVG Linear Gradient</title>
   <body>
   
      <h1>Sample SVG Linear Gradient</h1>
   
      <svg width="600" height="600">
      
         <defs>
            <linearGradient id="sampleGradient">
               <stop offset="0%" stop-color="#FF0000" />
               <stop offset="100%" stop-color="#00FFF00" />
            </linearGradient>
         </defs>
         
         <g>
            <text x="30" y="50" >Using Linear Gradient: </text>
            <rect x="100" y="100" width="200" height="200" stroke="green" stroke-width="3" 
            fill="url(#sampleGradient)" />
         </g>
         
      </svg>
   
   </body>
</html>
  • One <linearGradient> element defined as sampleGradient.

  • In linearGradient, two offsets are defined with two colors.

  • in rect element, in fill attribute, url of the gradient is specified to fill the rectangle with gradient created earlier.

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

Radial Gradients

Declaration

Following is the syntax declaration of <radialGradient> element. We've shown main attributes only.

<radialGradient
   gradientUnits ="units to define co-ordinate system of contents of gradient"
   gradientTransform = "definition of an additional transformation from the gradient coordinate system onto the target coordinate system"
   
   cx="x-axis co-ordinate of center of circle." 
   cy="y-axis co-ordinate of center of circle."     
   
   r="radius of circle" 
   
   fx="focal point for the radial gradient"     
   fy="focal point for the radial gradient"     
   
   spreadMethod="indicates method of spreading the gradient within graphics element"
   xlink:href="reference to another gradient" >
</radialGradient>

Attributes

Sr.No. Name & Description
1 gradientUnits − units to define the coordinate system for the various length values within the gradient. If gradientUnits="userSpaceOnUse", values represent values in the current user coordinate system in place at the time when the gradient element is used. If patternContentUnits="objectBoundingBox", values represent values in fractions or percentages of the bounding box on the referencing element in place at the time when the gradient element is used. Default is userSpaceOnUse.
2 cx − x-axis co-ordinate of the center of largest circle of gradient vector. Defeault is 0.
3 cy − y-axis co-ordinate of the center of largest circle of gradient vector. Default is 0.
4 r − radius of the center of largest circle of gradient vector. Defeault is 0.
5 fx − focal point of radial gradient. Default is 0.
6 fy − focal point of radial gradient. Default is 0.
7 spreadMethod − indicates method of spreading the gradient within graphics element. Default is 'pad'.
8 xlink:href − used to refer to another gradient.

Example

testSVG.htm

<html>
   <title>SVG Radial Gradient</title>
   <body>
      
      <h1>Sample SVG Radial Gradient</h1>
      
      <svg width="600" height="600">
         <defs>
            <radialGradient id="sampleGradient">
               <stop offset="0%" stop-color="#FF0000" />
               <stop offset="100%" stop-color="#00FFF00" />
            </radialGradient>
         </defs>
         
         <g>
            <text x="30" y="50" >Using Radial Gradient: </text>
            <rect x="100" y="100" width="200" height="200" stroke="green" stroke-width="3"
            fill="url(#sampleGradient)" />
         </g>
      </svg>
      
   </body>
</html>
  • One <radialGradient> element defined as sampleGradient.

  • In radialGradient, two offsets are defined with two colors.

  • in rect element, in fill attribute, url of the gradient is specified to fill the rectangle with gradient created earlier.

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering.

SVG - Interactivity

SVG images can be made responsive to user actions. SVG supports pointer events, keyboard events and document events. Consider the following example.

Example

testSVG.htm

<html>
   <title>SVG Interactivity</title>
   <body>
      
      <h1>Sample Interactivity</h1>
      
      <svg width="600" height="600">
         <script type="text/JavaScript">
            <![CDATA[
               function showColor() {
                  alert("Color of the Rectangle is: "+
                  document.getElementById("rect1").getAttributeNS(null,"fill"));
               }
               
               function showArea(event){
                  var width = parseFloat(event.target.getAttributeNS(null,"width"));
                  var height = parseFloat(event.target.getAttributeNS(null,"height"));
                  alert("Area of the rectangle is: " +width +"x"+ height);
               }
               
               function showRootChildrenCount() {
                  alert("Total Children: "+document.documentElement.childNodes.length);
               }
            ]]>
         </script>
         
         <g>
            <text x="30" y="50" onClick="showColor()">Click me to show rectangle color.</text>
            
            <rect id="rect1" x="100" y="100" width="200" height="200" 
            stroke="green" stroke-width="3" fill="red" 
            onClick="showArea(event)"/>
            
            <text x="30" y="400" onClick="showRootChildrenCount()">
            Click me to print child node count.</text>
         </g>
      </svg>
   
   </body>
</html>

Explaination

  • SVG supports JavaScript/ECMAScript functions. Script block is to be in CDATA block consider character data support in XML.

  • SVG elements support mouse events, keyboard events. We've used onClick event to call a javascript functions.

  • In javascript functions, document represents SVG document and can be used to get the SVG elements.

  • In javascript functions, event represents current event and can be used to get the target element on which event got raised.

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering. Click on each text and rectangle to see the result.

SVG - Linking

<a> element is used to create hyperlink. "xlink:href" attribute is used to pass the IRI (Internationalized Resource Identifiers) which is complementary to URI (Uniform Resource Identifiers).

Declaration

Following is the syntax declaration of <a> element. We've shown main attributes only.

<a
   xlink:show = "new" | "replace"
   xlink:actuate = "onRequest"
   xlink:href = "<IRI>"
   target = "_replace" | "_self" | "_parent" | "_top" | "_blank" | "<XML-Name>" >
</a>

Attributes

Sr.No. Name & Description
1 xlink:show − for documentation purpose for XLink aware processors. Default is new.
2 xlink:actuate − for documentation purpose for XLink aware processors.
3 xlink:href − location of the referenced object.
4 target − used when targets for the ending resource are possible.

Example

testSVG.htm

<html>
   <title>SVG Linking</title>
   <body>
   
      <h1>Sample Link</h1>
      
      <svg width="800" height="800">
         <g>
            <a xlink:href="http://www.yoursite.com"> 
               <text x="0" y="15" fill="black" >
               Click me to load yoursite DOT COM.</text>
            </a>
         </g> 
         
         <g>
            <text x="0" y="65" fill="black" >
            Click in the rectangle to load yoursite DOT COM</text>
            
            <a xlink:href="http://www.yoursite.com"> 
               <rect x="100" y="80" width="300" height="100"
               style="fill:rgb(121,0,121);stroke-width:3;stroke:rgb(0,0,0)" /> 
            </a>
         </g>
      </svg>
   
   </body>
</html>

Output

Open textSVG.htm in Chrome web browser. You can use Chrome/Firefox/Opera to view SVG image directly without any plugin. Internet Explorer 9 and higher also supports SVG image rendering. Click on link and rectangle to see the result.

script.aculo.us Tutorial

posted on June 11, 2021

tags:

What is script.aculo.us?

script.aculo.us is a JavaScript library built on top of the Prototype JavaScript Framework, enhancing the GUI and giving Web 2.0 experience to the web users.

script.aculo.us was developed by Thomas Fuchs and it was first released to the public in June 2005.

script.aculo.us provides dynamic visual effects and user interface elements via the Document Object Model (DOM).

The Prototype JavaScript Framework is a JavaScript framework created by Sam Stephenson that provides an Ajax framework and other utilities.

How to Install script.aculo.us?

It is quite simple to install the script.aculo.us library. It can be set up in three simple steps −

  • Go to the download page to download the latest version in a convenient package.

  • Unpack the downloaded package and you will find the following folders −

    • lib − contains prototype.js file.

    • src − contains the following 8 files −

      • builder.js
      • controls.js
      • dragdrop.js
      • effects.js
      • scriptaculous.js
      • slider.js
      • sound.js
      • unittest.js
    • test − contains files for testing purpose.

    • CHANGELOG − File that contains the history of all the changes.

    • MIT-LICENSE − File describing the licensing terms.

    • README − File describing the installation package including the installation instructions.

  • Now put the following files in a directory of your website, e.g. /javascript.

    • builder.js
    • controls.js
    • dragdrop.js
    • effects.js
    • scriptaculous.js
    • slider.js
    • prototype.js

NOTE − The sound.js and unittest.js files are optional

How to Use script.aculo.us Library?

Now you can include script.aculo.us script as follows −


   
      </span><span class="pln">script.aculo.us examples</span><span class="tag">
      
      

Dragging Things Around

It is very simple to make an item draggable using script.aculo.us. It requires creating an instance of the Draggable class, and identifying the element to be made draggable.

Draggable Syntax

new Draggable( element, options );

The first parameter to the constructor identifies the element to be made draggable either as the id of the element, or a reference to the element. The second parameter specifies optional information on how the draggable element is to behave.

Draggable Options

You can use one or more of the following options while creating your draggable object.

Option Description Examples
revert If set to true, the element returns to its original position when the drag ends. Also specifies whether the reverteffect callback will be invoked when the drag operation stops. Defaults to false.

Example

snap Used to cause a draggable to snap to a grid or to constrain its movement. If false (default), no snapping or constraining occurs.
  • If it is assigned an integer x, the draggable will snap to a grid of x pixels.

  • If an array [x, y], the horizontal dragging will snap to a grid of x pixels and the vertical will snap to y pixels.

  • It can also be a function conforming to Function( x , y , draggable ) that returns an array [x, y].

Example

zindex Specifies the CSS z-index to be applied to the element during a drag operation. By default, the element's z-index is set to 1000 while dragging.

Example

ghosting Boolean determining whether the draggable should be cloned for dragging, leaving the original in place until the clone is dropped. Defaults to false.

Example

constraint A string used to limit the draggable directions, either horizontal or vertical. Defaults to null which means free movement.

Example

handle Specifies an element to be used as the handle to start the drag operation. By default, an element is its own handle.

Example

starteffect An effect called on element when dragging starts. By default, it changes the element's opacity to 0.2 in 0.2 seconds.

Example

reverteffect An effect called on element when the drag is reverted. Defaults to a smooth slide to element's original position.Called only if revert is true.

Example

endeffect An effect called on element when dragging ends. By default, it changes the element's opacity to 1.0 in 0.2 seconds.

Example

Callback Options

Additionally, you can use any of the following callback functions in the options parameter −

Function Description Examples
onStart Called when a drag is initiated.

Example

onDrag Called repeatedly when a mouse moves, if mouse position changes from previous call.

Example

change Called just as onDrag (which is the preferred callback).

Example

onEnd Called when a drag is ended.

Example

Except for the "change" callback, each of these callbacks accepts two parameters: the Draggable object, and the mouse event object.

Draggable Example

Here, we define 5 elements that are made draggable: three

elements, an element, and a element. The purpose of the three different
elements is to demonstrate that regardless of whether an element starts off with a positioning rule of static (the default), relative, or absolute, the drag behavior is unaffected.

 

Live Demo

   
      </span><span class="pln">Draggables Elements</span><span class="tag">
		
      
      
      
      
   

   
       id = "normaldiv">
         This is a normal div and this is dragable.
      
id = "relativediv" style="position: relative;"> This is a relative div and this is dragable.

id = "absolutediv" style="position: absolute;"> This is an absolute div and this dragable. /> id = "image" src = "/images/scriptaculous.gif"/>

Let part id = "span" style = "color: blue;"> This is middle part Yes, only middle part is dragable.

This will produce following result −

Dropping Dragged Things

An element is converted into a drop target via a call to the add() method within a namespace called Droppables.

The Droppables namespace has two important methods: add() to create a drop target, and remove() to remove a drop target.

Syntax

Here is the syntax of the add() method to create a drop target. The add() method creates a drop target out of the element passed as its first parameter, using the options in the hash passed as the second.

Droppables.add( element, options );

The syntax for remove() is even more simpler. The remove() method removes the drop target behavior from the passed element.

Droppables.remove(element);

Options

You can use one or more of the following options while creating your draggable object.

Option Description Examples
Hoverclass The name of a CSS class that will be added to the element while the droppable is active (has an acceptable draggable hovering over it). Defaults to null.

Example

Accept A string or an array of strings describing CSS classes. The droppable will only accept draggables that have one or more of these CSS classes.

Example

Containment Specifies an element, or array of elements, that must be a parent of a draggable item in order for it to be accepted by the drop target. By default, no containment constraints are applied.

Example

Overlap If set to 'horizontal' or 'vertical', the droppable will only react to a Draggable if its overlapping by more than 50% in the given direction. Used by Sortables, discussed in the next chapter.
greedy If true (default), it stops hovering other droppables, under the draggable won't be searched.

Example

Callback Options

Additionally, you can use any of the following callback functions in the options parameter −

Function Description Examples
onHover Specifies a callback function that is activated when a suitable draggable item hovers over the drop target. Used by Sortables, discussed in the next chapter.
onDrop Specifies a callback function that is called when a suitable draggable element is dropped onto the drop target.

Example

Example

Here, the first part of this example is similar to our previous example, except that we have used Prototype's handy $A() function to convert a node list of all the elements in the element with the id of draggables to an array.

Live Demo

   
      </span><span class="pln">Drag and Drop Example</span><span class="tag">
		
      
      
		
      

      

This will produce following result −

script.aculo.us - Sorting Elements

Many times, you need to provide the user with the ability to reorder elements (such as items in a list) by dragging them.

Without drag and drop, reordering can be a nightmare, but script.aculo.us provides extended reordering support out of the box through the Sortable class. The element to become Sortable is passed to the create() method in the Sortable namespace.

A Sortable consists of item elements in a container element. When you create a new Sortable, it takes care of the creation of the corresponding Draggables and Droppables.

To use script.aculo.us's Sortable capabilities, you'll need to load the dragdrop module, which also requires the effects module. So your minimum loading for script.aculo.us will look like this −



Sortable Syntax

Here is the syntax of the create() method to create a sortable item. The create() method takes the id of a container element and sorts them out based on the passed options.

Sortable.create('id_of_container',[options]);

Use Sortable.destroy to completely remove all the event handlers and references to a Sortable created by Sortable.create.

NOTE − A call to Sortable.create, implicitly calls on Sortable.destroy if the referenced element was already a Sortable. Here is the simple syntax to call the destroy function.

Sortable.destroy( element );

Sortable Options

You can use one or more of the following options while creating your Sortable object.

Sr.No Option & Description
1

tag

Specifies the type of the elements within the sortable container that are to be sortable via drag and drop. Defaults to 'li'.

2

only

Specifies a CSS class name, or array of class names, that a draggable item must posses in order to be accepted by the drop target. This is similar to the accept option of Draggable. By default, no class name constraints are applied.

3

overlap

One of false, horizontal or vertical. Controls the point at which a reordering is triggered. Defaults to vertical.

4

constraint

One of false, horizontal or vertical. Constrains the movement of dragged sortable elements. Defaults to vertical.

5

containment

Enables dragging and dropping between Sortables. Takes an array of elements or element-ids. Important note: To ensure that two way dragging between containers is possible, place all Sortable.create calls after the container elements.

6

handle

Same as the Draggable option of the same name, specifying an element to be used to initiate drag operations. By default, each element is its own handle.

7

hoverclass

Specifies a CSS class name to be applied to non-dragged sortable elements as a dragged element passes over them. By default, no CSS class name is applied.
8

ghosting

Similar to the Draggable option of the same name, If true, this option causes the original element of a drag operation to stay in place while a semi-transparent copy of the element is moved along with the mouse pointer. Defaults to false. This option does not work with IE.

9

dropOnEmpty

If true, it allows sortable elements to be dropped onto an empty list. Defaults to false.

10

scroll

If the sortable container possesses a scrollbar due to the setting of the CSS overflow attribute, this option enables auto-scrolling of the list beyond the visible elements. Defaults to false.

12

scrollSensitivity

When scrolling is enabled, it adjusts the point at which scrolling is triggered. Defaults to 20.

13

scrollSpeed

When scrolling is enabled, it adjusts the scroll speed. Defaults to 15.

14

tree

If true, it enables sorting with sub-elements within the sortable element. Defaults to false.

15

treeTag

If the tree option is enabled, it specifies the container element type of the sub-element whose children takes part in the sortable behavior. Defaults to 'ul'.

You can provide the following callbacks in the options parameter −

Sr.No Option & Description
1

onChange

A function that will be called upon whenever the sort order changes while dragging. When dragging from one Sortable to another, the callback is called once on each Sortable. Gets the affected element as its parameter.

2

onUpdate

A function that will be called upon the termination of a drag operation that results in a change in element order.

Sorting Examples

This demo has been verified to work in IE 6.0. It also works in the latest version of Firefox.

Live Demo

   
      </span><span class="pln">Sorting Example</span><span class="tag">
		
      
      
		
      

      

Use our online compiler for a better understanding of the code with different options discussed in the above table.

This will produce following result −

Note the usage of tag:'li'. Similarly, you can sort the following list of images available in

 

Live Demo

   
      </span><span class="pln">Sorting Example</span><span class="tag">
		
      
      
		
      

      

This will produce following result −

Serializing the Sortable Elements

The Sortable object also provides a function Sortable.serialize() to serialize the Sortable in a format suitable for HTTP GET or POST requests. This can be used to submit the order of the Sortable via an Ajax call.

Syntax

Sortable.serialize(element, options);

Options

You can use one or more of the following options while creating your Sortable object.

Sr.No Option & Description
1

tag

Sets the kind of tag that will be serialized. This will be similar to what is used in Sortable.create.

2

name

Sets the name of the key that will be used to create the key/value pairs for serializing in HTTP GET/POST format. So if the name were to be xyz, the query string would look like −

xyz[]=value1 & xyz[]=value2 & xyz[]=value3

Where the values are derived from the child elements in the order that they appear within the container.

Serialize Examples

In this example, the output of the serialization will only give the numbers after the underscore in the list item IDs.

To try, leave the lists in their original order, press the button to see the serialization of the lists. Now, re-order some elements and click the button again.

Live Demo

   
      </span><span class="pln">Sorting Example</span><span class="tag">
		
      
      
		
       

This will produce following result −

Moving Items between Sortables

The following example shows how to move items from one list to another list.

Live Demo

   
      </span><span class="pln">Sorting Example</span><span class="tag">
		
      
      
		
      

      

Note that the containment option for each container lists both the containers as containment elements. By doing so, we have enabled the child elements to be sorted within the context of their parent; It also enables them to be moved between the two containers.

We set dropOnEmpty to true for both the lists. To see the effect this option has on that list, move all the elements from one list into other so that one list is empty. You will find that it is allowing to drop element on empty list.

This will produce following result −

Binding to Ajax

Of course, onUpdate is a prime candidate for triggering Ajax notifications to the server, for instance when the user reorders a to-do list or some other data set. Combining Ajax.Request and Sortable.serialize makes live persistence simple enough −

Live Demo

   
      </span><span class="pln">Sorting Example</span><span class="tag">
		
      
      
      
      

      

Sortable.serialize creates a string like: List[] = 1 & List[] = 2 & List[] = 3 &List[] = 4, where the numbers are the identifier parts of the list element ids after the underscore.

Now we need to code file.php, which will parse posted data as parse_str($_POST['data']); and you can do whatever you want to do with this sorted data.

To learn more about AJAX, please go through our simple Ajax Tutorial.

script.aculo.us - Create Sliders

Sliders are thin tracks with one or more handles on them that the user can drag along the track.

The goal of a slider is to provide an alternative input method for defining a numerical value; the slider represents a range, and sliding a handle along the track defines a value within this range.

Sliders can be in either horizontal or vertical orientation. When horizontal, the left end of the track usually represents the lowest value, while in a vertical orientation, the bottom of the slide is usually the lowest value.

To use script.aculo.us's slider capabilities, you'll need to load the slider.js module along with the prototype.js module. So your minimum loading for script.aculo.us will look like this −



      
		
      
		
      

Points to note −

  • You can change the slider image of any slider using CSS. Use CSS properties background-image: url(track.gif) and background-repeat: no-repeat to set the slider image.

  • The range value can be specified using $R(minValue, MaxValue). For example, $R(1, 100).

  • The range value can be specified in terms of specific values. For example values: [1,25,50,75,100]. In this case, the slider would only achieve the discrete values listed as the handle was moved.

  • At any time, the value of the slider can be set under program control by calling the setValue() method of the slider instance, as in: sliderInstance.setValue(50);

This will produce following result −

script.aculo.us - Auto Completion

Out of the box, script.aculo.us supports two sources for auto-completion −

  • Remote sources (obtained through Ajax),
  • Local sources (string arrays in your web page's scripts).

Depending on the source you're planning to use, you'll instantiate Ajax.Autocompleter or Autocompleter.Local, respectively. Although equipped with specific options, these two objects share a large feature set and provide a uniform user experience.

There are four things you'll always pass to these objects while building them −

  • The text field you want to make autocompletable. As usual, you can pass the field itself or the value of its id = attribute.

  • The container for autocompletion choices, which will end up holding a

      list of options to pick from. Again, pass the element directly or its id =. This element is most often a simple
      .

       

       

    • The data source, which will be expressed, depending on the source type, as a JavaScript array of strings or as a URL to the remote source.

    • Finally, the options. As always, they're provided as a hash of sorts, and both autocompletion objects can make do with no custom option; there are suitable defaults for everything.

    To use script.aculo.us's autocompletion capabilities, you'll need to load the controls.js and effects.js modules along with the prototype.js module. So, your minimum loading for script.aculo.us will look like this −

    
    
    

    Creating an Ajax Auto-Completer

    The construction syntax is as follows −

    new Ajax.Autocompleter(element, container, url [ , options ] )
    

    The constructor for the Ajax.Autocompleter accepts four parameters −

    • The element name or reference to a text field that is to be populated with a data choice.

    • The element name or reference to a

      element to be used as a menu of choices by the control.

       

    • The URL of the server-side resource that will supply the choices.

    • The usual options hash.

    Options

    You can use one or more of the following options while creating your Ajax.Autocompleter object.

    Sr.No Option & Description
    1

    paramName

    The name of the query parameter containing the content of the text field that is posted to the server-side resource. Defaults to the name of the text field.

    2

    minChars

    Number of characters that must be entered before a server-side request for choices can be fired off. Defaults to 1.

    3

    Frequency

    The interval, in seconds, between internal checks to see if a request to the server-side resource should be posted. Defaults to 0.4.

    4

    Indicator

    The id or reference to an element to be displayed while a server-side request for choices is underway. If omitted, no element is revealed.

    5

    Parameters

    A text string containing extra query parameters to be passed to the server-side resource.

    6

    updateElement

    A callback function to be triggered when the user selects one of the choices returned from the server that replaces the internal function that updates the text field with the chosen value.

    7

    afterUpdateElement

    A callback function to be triggered after the updateElement function has been executed.

    8

    Tokens

    A single text string, or array of text strings that indicate tokens to be used as delimiters to allow multiple elements to be entered into the text field, each of which can be auto-completed individually.

    Example

    Live Demo
    
       
          </span><span class="pln">Simple Ajax Auto-completer Example</span><span class="tag">
    		
          
          
          
          
       
       
       
          

    Type something in this box and then select suggested option from the list

    Text field: type = "text" id = "autoCompleteTextField"/> id = "autoCompleteMenu">

    Now, we need a server side to access this page and serve the data source URL (serverSideScript.php). You will keep a complete logic to display suggestions in this script.

    Just for example, we are keeping a simple HTML text in serverSideScript.php. You can write your script using CGI, PHP, Ruby, or any other server side scripting to choose appropriate suggestions and format them in the form of

    • ...
    and pass them back to the caller program.

     

    • One
    • Two
    • Three
    • Four
    • Five
    • Six

    This will produce following result −

    with different options discussed in the above table.

    Creating a Local Auto-Completer

    Creating a local auto-completer is almost identical to creating an Ajax Auto-completer as we have discussed in the previous section.

    The major difference lies in how the backing data set to use for auto-completion is identified to the control.

    With an Ajax Auto-completer, we have supplied the URL of a server-side resource that would perform the necessary filtering, given the user input, and return only the data elements that matched. With a Local Autocompleter, we supply the full list of data element instead, as a JavaScript String array, and the control itself performs the filtering operation within its own client code.

    The whole construction syntax is actually as follows −

    new Autocompleter.Local(field, container, dataSource [ , options ] );
    

    The constructor for the Autocompleter.Local accepts four parameters −

    • The element name or reference to a text field that is to be populated with a data choice.

    • The element name or reference to a

      element to be used as a menu of choices by the control

       

    • For the third parameter, instead of a URL as with the server-assisted auto-completer, we supply a small String array, which contains all of the possible values.

    • The usual options hash.

    Options

    You can use one or more of the following options while creating your Autocompleter.Local object.

    Sr.No Option & Description
    1

    Choices

    The number of choices to display. Defaults to 10.

    2

    partialSearch

    Enables matching at the beginning of words embedded within the completion strings. Defaults to true.

    3

    fullSearch

    Enables matching anywhere within the completion strings. Defaults to false.

    4

    partialChars

    Defines the number of characters that must be typed before any partial matching is attempted. Defaults to 2.

    5

    ignoreCase

    Ignores case when matching. Defaults to true.

    Example

    Live Demo
    
       
          </span><span class="pln">Simple Ajax Auto-completer Example</span><span class="tag">
    		
          
          
          
          
       
    
       
          

    Type something in this box and then select suggested option from the list

    Text field: type = "text" id = "autoCompleteTextField"/> id = "autoCompleteMenu">

    When displayed, and after the character 'a' is typed into the text box, it displays all the matching options.

    Use our online compiler for a better understanding of the code with different options discussed in the above table.

    This will produce following result −

    script.aculo.us - In-Place Editing

    In-place editing is one of the hallmarks of Web 2.0.style applications.

    In-place editing is about taking non-editable content, such as a

    ,

    , or
    , and letting the user edit its contents by simply clicking it.

     

    This turns the static element into an editable zone (either singleline or multiline) and pops up submit and cancel buttons (or links, depending on your options) for the user to commit or roll back the modification.

    It then synchronizes the edit on the server side through Ajax and makes the element non-editable again.

    To use script.aculo.us's in-place editing capabilities, you'll need to load the controls.js and effects.js modules along with the prototype.js module. So, your minimum loading for script.aculo.us will look like this −

    
    
    

    Creating an In-Place Text Editor

    The whole construction syntax is as follows −

    new Ajax.InPlaceEditor(element, url [ , options ] )
    

    The constructor for the Ajax.InPlaceEditor accepts three parameters −

    • The target element can either be a reference to the element itself or the id of the target element.

    • The second parameter to the Ajax.InPlaceEditor specifies the URL of a server-side script that is contacted when an edited value is completed.

    • The usual options hash.

    Options

    You can use one or more of the following options while creating your Ajax.InPlaceEditor object.

    Sr.No Option & Description
    1

    okButton

    A Boolean value indicating whether an "ok" button is to be shown or not. Defaults to true.

    2

    okText

    The text to be placed on the ok button. Defaults to "ok".

    3

    cancelLink

    A Boolean value indicating whether a cancel link should be displayed. Defaults to true.

    4

    cancelText

    The text of the cancel link. Defaults to "cancel".

    5

    savingText

    A text string displayed as the value of the control while the save operation (the request initiated by clicking the ok button) is processing. Defaults to "Saving".

    6

    clickToEditText

    The text string that appears as the control "tooltip" upon mouse-over.

    7

    rows

    The number of rows to appear when the edit control is active. Any number greater than 1 causes a text area element to be used rather than a text field element. Defaults to 1.

    8

    cols

    The number of columns when in active mode. If omitted, no column limit is imposed.

    9

    size

    Same as cols but only applies when rows is 1.

    10

    highlightcolor

    The color to apply to the background of the text element upon mouse-over. Defaults to a pale yellow.

    11

    highlightendcolor

    The color to which the highlight color fades to as an effect.

    Note − support seems to be spotty in some browsers.

    12

    loadingText

    The text to appear within the control during a load operation. The default is "Loading".

    13

    loadTextURL

    Specifies the URL of a server-side resource to be contacted in order to load the initial value of the editor when it enters active mode. By default, no backend load operation takes place and the initial value is the text of the target element.

    14

    externalControl

    An element that is to serve as an "external control" that triggers placing the editor into an active mode. This is useful if you want another button or other element to trigger editing the control.

    15

    ajaxOptions

    A hash object that will be passed to the underlying Prototype Ajax object to use as its options hash.

    Callback Options

    Additionally, you can use any of the following callback functions in the options parameter

    Sr.No Function & Description
    1

    onComplete

    A JavaScript function that is called upon successful completion of the save request. The default applies a highlight effect to the editor.

    2

    onFailure

    A JavaScript function that is called upon failure of the save request. The default issues an alert showing the failure message.

    3

    callback

    A JavaScript function that is called just prior to submitting the save request in order to obtain the query string to be sent to the request. The default function returns a query string equating the query parameter "value" to the value in the text control.

    CSS Styling and DOM id Options

    You can also use one the following options to control the behavior of in place editor −

    Sr.No Option & Description
    1

    savingClassName

    The CSS class name applied to the element while the save operation is in progress. This class is applied when the request to the saving URL is made, and is removed when the response is returned. The default value is "inplaceeditor-saving".

    2

    formClassName

    The CSS class name applied to the form created to contain the editor element. Defaults to "inplaceeditor-form".

    3

    formId

    The id applied to the form created to contain the editor element.

    Example

    Live Demo
    
       
          </span><span class="pln">Simple Ajax Auto-completer Example</span><span class="tag">
    		
          
          
          
          
       
       
       
          

    Click over the "Click me!" text and then change text and click OK.

    Try this example with different options.

    id = "theElement"> Click me!

    When displayed, click and edit the text. This rather trivial PHP script converts the value of a query parameter with the key "value" to its uppercase equivalent, and writes the result back to the response.

    Here is the content of transform.php script.

    php
       if( isset($_REQUEST["value"]) ) {
          $str = $_REQUEST["value"];
          $str = strtoupper($str);
          echo "$str";
       }
    ?>

    This will produce following result −

    The In-Place Collection Editor Options

    There is one more object called Ajax.InPlaceCollectionEditor, which supports in-place editing and gives you the option to select a value from the given options.

    The whole construction syntax is as follows −

    new Ajax.InPlaceCollectionEditor(element, url [ , options ] )
    

    The constructor for the Ajax.InPlaceCollectionEditor accepts three parameters −

    • The target element can either be a reference to the element itself or the id of the target element

    • The second parameter to the Ajax.InPlaceEditor specifies the URL of a server-side script that is contacted when an edited value is completed.

    • The usual options hash.

    Options

    Aside from the addition of the collection option, the list of options for the In-Place Collection Editor is a subset of the options inherited from the In-Place Text Editor.

    Sr.No Option & Description
    1

    okButton

    A Boolean value indicating whether an "ok" button is to be shown or not. Defaults to true.

    2

    okText

    The text to be placed on the ok button. Defaults to "ok".

    3

    cancelLink

    A Boolean value indicating whether a cancel link should be displayed. Defaults to true.

    4

    cancelText

    The text of the cancel link. Defaults to "cancel".

    5

    savingText

    A text string displayed as the value of the control while the save operation (the request initiated by clicking the ok button) is processing. Defaults to "Saving".

    6

    clickToEditText

    The text string that appears as the control "tooltip" upon mouse-over.

    7

    Highlightcolor

    The color to apply to the background of the text element upon mouse-over. Defaults to a pale yellow.

    8

    Highlightendcolor

    The color to which the highlight color fades to as an effect.

    Note − support seems to be spotty in some browsers.

    9

    Collection

    An array of items that are to be used to populate the select element options.

    10

    loadTextUrl

    Specifies the URL of a server-side resource to be contacted in order to load the initial value of the editor when it enters active mode. By default, no backend load operation takes place and the initial value is the text of the target element. In order for this option to be meaningful, it must return one of the items provided in the collection option to be set as the initial value of the select element.

    11

    externalControl

    An element that is to serve as an "external control" that triggers placing the editor into active mode. This is useful if you want another button or other element to trigger editing the control.

    12

    ajaxOptions

    A hash object that will be passed to the underlying Prototype Ajax object to use as its options hash.

    Callback Options

    Additionally, you can use any of the following callback functions in the options parameter −

    Sr.No Function & Description
    1

    onComplete

    A JavaScript function that is called upon successful completion of the save request. The default applies a highlight effect to the editor.

    2

    onFailure

    A JavaScript function that is called upon failure of the save request. The default issues an alert showing the failure message.

    CSS Styling and DOM id Options

    You can also use one the following options to control the behavior of in-place editor −

    Sr.No Option & Description
    1

    savingClassName

    The CSS class name applied to the element while the save operation is in progress. This class is applied when the request to the saving URL is made, and is removed when the response is returned. The default value is "inplaceeditor-saving".

    2

    formClassName

    The CSS class name applied to the form created to contain the editor element. Defaults to "inplaceeditor-form".

    3

    formId

    The id applied to the form created to contain the editor element.

    Example

    Live Demo
    
       
          </span><span class="pln">Simple Ajax Auto-completer Example</span><span class="tag">
    		
          
          
          
          
       
       
       
          

    Click over the "Click me!" text and then change text and click OK.

    Try this example with different options.

    id = "theElement"> Click me!

    Here is the content of the transform.php script.

    php
       if( isset($_REQUEST["value"]) ) {
          $str = $_REQUEST["value"];
          $str = strtoupper($str);
          echo "$str";
       }
    ?>

    When displayed, click and select one of the displayed options. This rather trivial PHP script converts the value of the query parameter with the key "value" to its uppercase equivalent, and writes the result back to the response.

    Use our online compiler for a better understanding of the code with different options discussed in the above table.

What are the most expensive skills for freelancing?

posted on June 11, 2021

tags:

Highest Paying Freelancing Skills

1. Programming And Software Development

Programming jobs, especially software and mobile app development, pays the highest for freelancers. Only because it’s a skill that’s quite difficult to master and there aren’t many good coders out there. So, the demand for good coders is pretty high.

If you want to make an income like James, start learning to code. And I don’t mean learning through free courses on CodeAcademy or Udemy. They’ll only take you through the basics. You’ll need to invest some money and time into learning and practicing to develop proper coding skills.

Of course, you won’t be able to start charging $1,000 an hour right away. You’ll have to gradually build up your reputation. If you have solid skills in programming languages like iOS and WebGL, you could start charging somewhere around $150 per hour, or more.

According to a recent UpWork survey, Bitcoin developers also have high demand. Most Bitcoin developers earn over $200 per hour.

2. Social Video Marketing

In a surprise turn of events, a new skill is born—”social video marketing”. The skill ranked at the third place of the UpWork’s Q2 2019 fastest-growing skills list. And for good reason as well.

A quick search on the platform showed that this skill pays over $150 per hour for marketers.

It’s no surprise that this skill is in high demand. Especially given the rise of video content marketing. The booming social media channels such as TikTok, Instagram video, and YouTube, will keep this skill relevant for years to come.

If you’re skilled at creating video content, optimizing them for SEO, capturing audiences with new ideas and marketing strategies, this skill will help bring many gigs your way.

3. Web Design And Development

According to an UpWork statistics report, PHP Development is the most in-demand skill of 2015. Web Design ranks at the 7th spot.

There’s great demand for web designers. But, it’s worth noting that the freelance web design industry is pretty crowded right now because it’s easy to learn web design and start coding websites. Heck, even I did some web design work for a while and started my own web design agency. Spoiler alert! It didn’t go so well.

The best strategy would be to find a niche in the field. For example, Jonathan Wold made over $5,000 a month by building websites with WordPress and doing small theme customizations. You’ll probably be able to earn more if you offer the right kind of services to the right clients.

4. Content Marketing/Writing

Thanks to the boom in online marketing trends and the development of new methodologies, like Inbound Marketing, content writing is now considered as one of hottest fields for freelancers.

You don’t need to go anywhere to find proof of how well freelance writers are doing. Take me for example. Right now, I make around $5,000 a month (at least in most months) doing blogging work for businesses, writing, and content marketing work. And I know there are other freelance writers who do much better than me.

Although, not everyone can be a skilled writer. You need to write a lot, read a lot, and, more importantly, you’ll need a creative mind to write amazing articles that pay well. Your master’s degree in literature and the A+ essay skills from college won’t do you any good when working online either.

5. Graphic Design

Graphic design ranks at number 2 on the UpWork’s most in-demand skills list. And if you look at its top freelancers under the graphic design category, you’ll see some freelancers who make up to $85 per hour doing design work.

Infographic design has higher demand these days. Logo design, icon design, and illustrations pay pretty well too. But, like with content writing, to become a quality graphic designer, you’ll need to develop an eye for design.

6. Copywriters

Copywriters are different from content marketers and writers. These freelancers specialize in writing content for website pages, descriptions for products, services, etc.

The charge rates for copywriters depend on each freelancer’s level of experience and skill. Linda Formichelli, an experienced freelance copywriter, makes $250 per hour.

If you look at UpWork’s list of top copywriters, you’ll notice that they charge between $15 per hour to $100 per hour for copywriting jobs.

7. Video Editors

Freelance video editors in the US earns around $72,000 per year, while more experienced video editors make around $122,000 per year.

The demand for video editors in the freelance industry saw a rise in the last few years, thanks to the opportunities presented by platforms such as YouTube, Facebook, and Instagram.

If you’re good with putting together video clips and creating awesome video content, this could be a great future-proof career to get into.

Sencha Touch Tutorial

posted on June 9, 2021

tags:

Sencha Touch is a popular framework of Sencha for creating a user interface for mobile applications. It helps the developer create a mobile app using simple HTML, CSS, JS which supports many mobile devices such as android, IOS, BlackBerry, and Windows. It is based on MVC architecture. The latest version of Sencha Touch is 2.4.

History of Sencha Touch

After releasing Sencha's other product, ExtJs, which was for web application, there was a need to develop a framework which works on mobile devices too.

The first version of Sencha Touch was 0.9 beta version, which supported Android and IOS devices. Later, the first main release of Sencha Touch version 1.0 was in November 2010, which was the first stable version and supported Blackberry devices too.

The latest release of Sencha Touch is version 2.4 released in June 2015, which supports many devices such as Windows, Tizen along with Android, IOS, BlackBerry OS 10, Google Chrome for Android and mobile Safari, etc.

Features of Sencha Touch

Following are the most prominent features of Sencha Touch −

  • Customizable and more than 50 build in UI widgets with a collection of rich UI such as lists, carousels, forms, menus, and toolbars, built specifically for mobile platforms.

  • Code compatibility of new versions with the older one.

  • A flexible layout manager that helps organize the display of data and content across multiple mobile devices with different OS.

  • The framework includes a robust data package that can consume data from any backend data source.

  • Adaptive layouts, animations, and smooth scrolling for a better mobile web application experience for the use.

  • Out-of-the-box, native-looking themes for every major platform enables to make web and hybrid applications match the look and feel of the target platforms.

Sencha Touch ââ€â‚¬ Benefits

Sencha Touch is the leading standard for business-grade web application development. It offers the tools necessary to build robust applications for most of the mobile devices providing a single platform for developing applications. Following are some of the benefits −

  • Provides a responsive touch feature, hence the user can easily navigate while using the mobile app.

  • Provides compatibility with all the latest versions of IOS, Android and Blackberry, and Windows.

  • Provides fastest possible speed desirable for any mobile application.

  • Provides a cost-effective solution with its cross-platform compatibility.

  • Based on the native APIs and basic web development languages such as HTML, CSS, JS which makes it easier for a developer to understand Sencha Touch.

Sencha Touch ââ€â‚¬ Limitations

Sencha Touch API doesn't have the following capability −

  • The app does not have access to the device’s camera, contacts, and accelerometer.

  • It does not provide the push notification facility. For this, we have to use websockets or long polling.

  • According to general public license policy, it is free for open source applications however paid for commercial applications.

  • It is not good for hardcore graphics and animation apps such as for gaming apps.

Sencha Touch ââ€â‚¬ Tools

Sencha SDK

This is Sencha development kit used to create a skeleton of the project. We use the command "sencha -sdk path/to/touch generate app appName" to create an app with the name given in the command.

When the app is created, you can see the following files in the app −

  • app − This folder contains model, view, controller and store files for the app.

  • app.js − This is the main JS file for your application. From this file, the Sencha code flow starts.

  • app.json − This is the configuration file for the app, all the configuration details presents here.

  • index.html − This is the main html file where we include the app.js and other Sencha related files.

  • package.json − This file has all the dependency and other information related to the app.

  • resources − This folder includes all the CSS files and images required for the application.

Sencha CMD

Sencha CMD is a command line tool, which provides the features of Sencha Touch code minification, scaffolding, build generation, and other useful features for production purpose.

We use command "Sencha app build package" in the command prompt to build the application for this. Go to the app directory in the command prompt and type the above command. Once the build is successful, we will see the minified version of the application basically used for production purpose.

This can be downloaded from https://www.sencha.com/products/extjs/cmd-download/

Sencha Inspector

Sencha Inspector is a debugging tool to debug any issue in Sencha code during development.

Sencha Touch - Environment Setup

We have set up Sencha Touch Programming environment online, so that you can compile and execute all the available examples online. It gives you confidence in what you are reading and enables you to verify the programs with different options. Feel free to modify any example and execute it online.

<!DOCTYPE html>
<html>
   <head>
      <link href="http://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel="stylesheet" />
      <script type="text/javascript" src="http://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type="text/javascript">
        Ext.application({
           name: 'Sencha',
           launch: function() {
              Ext.create("Ext.tab.Panel", {
                 fullscreen: true,
                 items: [{
                    title: 'Home',
                    iconCls: 'home',
                    html: 'Welcome'
                 }]
              });
           }
        });
      </script>
   </head>
   <body>
   </body>
</html>

Local Environment Setup

This section guides you on how to download and set up sench Touch on your machine. Please follow the steps to set up the environment.

Downloading library files

Download a commercial version of Sencha Touch library files from sencha https://www.sencha.com. You will get the trial version from the site on your registered mail id which will be a zipped folder named sencha-touch-2.4.2-commercial.

Unzip the folder and you will find various JavaScript and CSS files which you will include in our application. We will mostly include following files:

(1) Javascript Files JS file which you can find under folder sencha-touch-2.4.2-commercial ouch-2.4.2 are :

File and Description
sencha-touch.js
This is the core file which contains all functionality to run the application.
sencha-touch-all.js
This file contains all the code minified with no comments in the file
sencha-touch-debug.js
This is the unminified version of sencha-touch-all.js for debugging purpose.
sencha-touch-all-debug.js
This file is also unminified and is used for development purpose as it contains all the comments and console logs also to check any errors/issue

You can add these files to your projects JS folder or you can give direct path where the file reside in your system.

(2) CSS Files There are number of theme based files which you can find under folder I:sencha touchsencha-touch-2.4.2-commercial ouch-2.4.2 esourcescsssencha-touch.css

These library files will be added in an Sencha Touch application as follows:

<html>
   <head>
    <script type="text/javascript" src="../sencha-touch-2.4.2-commercial/touch-2.4.2/sencha-touch-all.js"></script>  
    <link href="../sencha-touch-2.4.2-commercial/touch-2.4.2/resources/css/sencha-touch.css" rel="stylesheet" />
    <script type ="text/javascript" src = "app.js" > </script> 
   </head>
</html>

You will keep sencha Touch application code in app.js file.

CDN setup

CDN is content delivery network with which you do not need to download the Sencha touch library files instead you can directly add CDN link for ExtJS to your program as follows:

<html>
   <head>
    <script type="text/javascript" src="http://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>    
    <link href="http://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel="stylesheet" />
    <script type ="text/javascript" src = "app.js" > </script> 
   </head>
</html>

Popular Editors

As it is a JavaScript framework which is used for developing web applications, in our project we will have HTML, JS files and to write your Ext JS programs, you will need a text editor. There are even multiple IDEs available in the market. But for now, you can consider one of the following:

  • Notepad: On Windows machine you can use any simple text editor like Notepad (Recommended for this tutorial), Notepad++.
  • Brackets: is another popular IDE which can be downloaded from http://brackets.io/ .
  • Sublime: is another popular IDE which can be downloaded from https://www.sublimetext.com/3/ .

Sencha Touch - Naming Convention

Naming convention is a set of rules to be followed for identifiers. It makes the code easily readable and understandable for other programmers as well.

Naming convention in Sencha Touch follows the standard JavaScript convention, which is not mandatory but a good practice to follow. It should follow camel case syntax for naming the class, method, variable, and properties.

If the name is combined with two words, the second word will start with an uppercase letter always. For example, doLayout(), StudentForm, firstName, etc.

Sr.No. Name & Convention
1

Class Name

It should start with an uppercase letter, followed by camel case. For example, StudentClass

2

Method Name

It should start with a lowercase letter, followed by camel case. For example, studentMethod()

3

Variable Name

It should start with a lowercase letter, followed by camel case. For example, studentName

4

Constant Name

It should be in uppercase only. For example, COUNT, MAX_VALUE

5

Property Name

It should start with a lowercase letter, followed by camel case. For example, enableColumnResize = true

Sencha Touch - Architecture

The bottom layer for any mobile application is OS, on top of that anything or everything is built. Then we have the browsers on which we will be running the applications. It could be Chrome, Safari, IE anything. The upper layer is a W3 standards, which is common for all. Sencha Touch stands or is built on top of W3 standards, which is nothing but HTML5, which makes a single application compatible with different browsers of different devices.

Sencha Touch is a combination of three frameworks − ExtJs, JqTouch, and Raphael (vector drawing). It follows MVC architecture. MVC separates the code into more manageable chunks.

Although the architecture is not mandatory for the program, however, it is a best practice to follow this structure to make your code highly maintainable and organized.

Project Structure With Sencha Touch App

----------src
----------resources
-------------------CSS files
-------------------Images
----------JavaScript
--------------------App Folder
-------------------------------Controller
------------------------------------Contoller.js
-------------------------------Model
------------------------------------Model.js
-------------------------------Store
------------------------------------Store.js
-------------------------------View
------------------------------------View.js
-------------------------------Utils
------------------------------------Utils.js
--------------------------------app.js
-----------HTML files

Sencha Touch app folder will reside in the JavaScript folder of your project.

The App will contain controller, view, model, store, and utility files with app.js.

app.js − The main file from where the flow of program will start. It should be included in main HTML file using <script> tag. App calls the controller of application for rest of the functionality.

Controller.js − It is the controller file of Sencha Touch MVC architecture. This contains all the control of the application, the events listeners, and most of the functionality of the code. It performs the following tasks: routing, intermediate between view and model, and executes events.

View.js − It contains the interface part of the application, which shows up to the user. Sencha Touch uses various UI rich views, which can be extended and customized according to the requirement.

Store.js − It contains the locally cached data, which is to be rendered on view with the help of model objects. Store fetches the data using proxies, which has the path defined for services to fetch the backend data.

Model.js − It contains the objects which binds the store data to view. It is the representation of the real-world object, which basically deals with the database.

Utils.js − It is not included in MVC architecture but it is a best practice to use this so as to make the code clean, less complex, and more readable. We can write methods in this file and call them in controller or view renderer wherever required. It is helpful for code reusability purpose as well.

Sencha Touch - MVC

MVC stands for Model View Controller. It is an architectural pattern which separates the application into logical components making it more manageable.

The following diagram shows how MVC architecture works −

MVC

Controller − Controller controls whole application it notify view if model is changed and performs actions based on user inputs.

View − It contains the interface part of the application which is visual to user. It notify controller to change model on user input.

Model − It contains the objects which binds the store data to view. It is representation of the real world object which basically deals with database. It also notify controller for any change in view.

Sencha Touch - First Program

In this chapter, we will list down the steps to write the first Hello World program in Ext JS.

Step 1

Create an index.htm page in an editor of our choice. Include the required library files in the head section of html page as follows.

index.htm

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js">
      </script>
      <script type = "text/javascript">
         Ext.application( {
            name: 'Sencha', launch: function() {
               Ext.create("Ext.tab.Panel", {
                  fullscreen: true, items: [{
                     title: 'Home', iconCls: 'home', html: 'Welcome to sencha touch'
                  }]
               });
            }
         });
      </script>
   </head>
   
   <body>
   </body>
</html>

Explanation

  • Ext.application() method is the starting point of Sencha Touch application. It creates a global variable called 'Sencha' declared with the name property - all the Application's classes such as its Models, Views and Controllers will reside under this single namespace, which reduces the chances of colliding global variables and file names.

  • launch() method is called once the page is ready and all the JavaScript files are loaded.

  • Ext.create() method is used to create an object in Sencha Touch. Here, we are creating an object of simple panel class Ext.tab.Panel.

  • Ext.tab.Panel is the predefined class in Sencha Touch for creating a panel.

  • Every Sencha Touch class has different properties to perform some basic functionalities.

Ext.Panel class has various properties such as −

  • fullscreen property is to make use of a complete screen, hence the panel will take fullscreen space.

  • items property is the container for various items.

  • iconCls is the class used for displaying different icons.

  • title property is to provide the title to the panel.

  • html property is the html content to be shown in the panel.

Step 2

Open the index.htm file in a standard browser and you will get the following output.

Sencha Touch - Builds

Today's demand for a web application is to develop a fast application with less development efforts. Sencha Touch helps in doing so with ease as it provide a number of build libraries to choose from, based on the development or production code along with the facility to create a custom build.

Sencha Touch build libraries loads the classes dynamically. Dynamic loading stands for the classes that gets loaded when required and only those classes will be included which are required in the application. This makes the application run faster as the number of files to be loaded reduces, simultaneously decreasing the time to load.

Sencha Touch 2.x provides the following five build libraries.

Sr.No. Builds & Usage
1

sencha-touchdebug.js

This build is used while developing the application locally. It is a nonminified version with all the comments and debug logs for easy debugging while development.

2

senchatouch.js

This file is used for production purpose. It is the minified version when we have a custom build.

3

sencha-touchall.js

This file is used for production purpose. It is the minified version when we do not have a custom build.

4

sencha-touchall-debug.js

This file is used for debugging in production. It is not minified and has all the comments and debug logs.

5

sencha-touchall-compat.js

This build is used to migrate the version 1.x to version 2.x. It gives a warning wherever version 1.x code is not compatible and needs code modification.

With the above mentioned builds, Sencha Touch provides a facility to create custom builds.

Advantages of Having a Custom Build

Custom build does not load all the touch files. It loads only those files, which we are using in the application, which makes the application faster and easily maintainable.

Sencha CMD is used to create a custom build. To create a custom build in Sencha CMD, go to the directory where the app file resides and type one of the following commands to create a build.

Sr.No. Command & Usage
1

sencha app build native

Builds the app and prepares a file called packager.temp.json that you can use to package an application--the packager.temp.json is the same as packager.json, but contains additional paths.

2

sencha app build -run native

Builds and automatically packages the application, and launches the appropriate simulator.

3

sencha app build package

Builds the app with packaging support, but does not configure a packager JSON file. This is useful for projects that manually maintain multiple packager.json files.

Once the build is successful, it will generate all-classes.js file which we need to include in our index.html to make it production ready.

Following code shows the changes to be done for production ready code.

Index.html before building application

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-debug.js"></script>
      <script type = "text/javascript" src = "app.js"> </script>
   </head>
   <body>
   </body>
</html>

Index.html after building the application

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch.js"></script>
      <script type = "text/javascript" src = "app.js"> </script>
      <script type = "text/javascript" src = "app-classes.js"> </script>
   </head>
   <body>
   </body>
</html>

Sencha Touch - Migration

Sencha Touch comes with various rectifications from the earlier version.

Sencha Touch 2 comes with the backward compatibility build, which makes the migration process easier from version 1.x to 2.x.

This build just makes the work easier by providing a warning and the logs whenever any migration issue occurs or code change is required, so the user will get to know where the changes are must, to make sure the application works with the latest version.

Sencha Touch 2.x migration requires the following code changes.

Class System

Code in Sencha Touch 1.x

MyApp.view.StudentPanel = Ext.extend(Ext.Panel, {
   scroll: 'vertical',
   html: 'Student Panel'
   initComponent: function() {
      Ext.getCmp('StudentIdDiv').update('This is a Student panel');
   }
});

Code in Sencha Touch 2.x

Ext.define('MyApp.view.StudentPanel', {
   extend: 'Ext.Panel',

   config: {
      scroll: 'vertical',
      html: 'Student Panel'
   },

   initialize: function() {
      Ext.getCmp('StudentIdDiv').setHtml('This is a Student panel')
   }
});

By looking at both the versions, you can see the way to create class is changes which is now inspired by ExtJs such as −

  • Ext.extend is changed to Ext.define.

  • All the configuration parameters related to the class are now defined under config parameter.

  • The initComponent is changed to initialize() method.

  • In Sencha Touch 2.x, we can have setHtml() and getHtml() functions to update html or to get the value.

MVC Architecture

Sencha Touch 1.x code was modular and based on MVC architecture. Sencha Touch 2.x follows a different syntax for writing model, view, and controller. Let’s see the difference of model, view, and controller files in different versions.

Model

Code in Sencha Touch 1.x

Ext.regModel('MyApp.model.StudentModel', {
   fields: [
      {name: 'name',  type: 'string'},
      {name: 'age',   type: 'int'}
   ]
});

Code in Sencha Touch 2.x

Ext.define('MyApp.model.StudentModel', {
   extend: 'Ext.data.Model', config: {
      fields: [
         {name: 'name',  type: 'string'},
         {name: 'age',   type: 'int'}
      ]
   }
});

Ext.regModel is changed to Ext.define which extends Ext.data.Model.

All the fields come under config section now in 2.x version.

View

Code in Sencha Touch 1.x

Ext.Panel("studentView", {
   items: [{}]
});

Code in Sencha Touch 2.x

Ext.define('MyApp.view.StudentView', {
   extend: 'Ext.tab.Panel',
   items: [{}]
});  

View is almost the same, the only change being the view name follows the 2.x version namespacing such as Myapp.view.StudentView and code is writing in Ext.define method as like model.

Controller

Code in Sencha Touch 1.x

Ext.regController("studentController", {
   someMethod: function() {
      alert('Method is called');
   }
});

Code in Sencha Touch 2.x

Ext.define('MyApp.controller.studentController', {
   extend: 'Ext.app.Controller', someMethod: function() {
      alert('Method is called');
   }
});

Same as model in controller. Also the Ext.regController is changed into Ext.define, which extends Ext.app.Controller.

Application

Code in Sencha Touch 1.x

Ext.application({
   name: 'MyApp',
   launch: function() {
      Ext.create('MyApp.view.StudentView');
   }
});

Code in Sencha Touch 2.x

Ext.application({
   name: 'MyApp',
   models: ['studentModel'],
   controllers: ['studentController'],
   views: ['studentView'],
   stores: ['studentStore'],

   launch: function() {
      Ext.create('MyApp.view.Main');
   }
});

The major difference between version 1.x and version 2.x is, in 2.x we declare all model, views, controllers, and stores in the application itself.

Sencha Touch - Core Concept

Sencha Touch has various core concepts such as class system, ajax, controllers, etc.

Following table lists the link for core concepts of Sencha Touch.

Sr.No. Concept & Description Link
1 Class System
2 Components
3 Controllers
4 BlackBerry support
5 Use of Ajax

Sencha Touch - Data Package

Data package in Sencha Touch is responsible for carrying out any kind of data manipulation either storing or loading the data.

Data packages are related to model, store, and proxies.

Sr.No. Concept & Description Link
1

Model

It is the collection of data and fields with which we display all the values on UI. Description

2

Store

It is a collection of model instances which basically stores the data locally. In store we write all the events and rest calls to get data. Description

3

Proxy

It is basically responsible for loading data in store. Mostly we use ajax proxy to load store data. Description

Sencha Touch - Theme

Sencha Touch provides a number of themes to be used in your applications. You can add different themes in place of classic theme and see the difference in the output based on the device we are using for the application. This is done simply by replacing the theme CSS file as explained in the following example.

Desktop Theme

Consider your very first Hello World application. The following CSS from the application is used for desktop theme.

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css

To see the effect, try the following program −

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type="text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.application({
            name: 'Sencha',
            launch: function() {
               Ext.create("Ext.tab.Panel", {
                  fullscreen: true,
                  items: [{
                     title: 'Home',
                     iconCls: 'home',
                     html: 'Welcome to sencha touch'
                  }]
               });
            }
         });
      </script>
   </head>
</html>

This will produce following result −

Windows Theme

Consider your very first Hello World application. Remove the following CSS from the application −

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css

Add the following CSS to use Windows theme.

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/wp.css

To see the effect, try the following program −

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/wp.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.application({
            name: 'Sencha',
            launch: function() {
               Ext.create("Ext.tab.Panel", {
                  fullscreen: true,
                  items: [{
                     title: 'Home',
                     iconCls: 'home',
                     html: 'Welcome to sencha touch'
                  }]
               });
            }
         });
      </script>
   </head>
</html>

This will produce following result −

IOS Theme

Consider your very first Hello World application. Remove the following CSS from the application.

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css

Add the following CSS to use Windows theme

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/cupertino.css

To see the effect, try the following program −

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/cupertino.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.application({
            name: 'Sencha',
            launch: function() {
               Ext.create("Ext.tab.Panel", {
                  fullscreen: true,
                  items: [{
                     title: 'Home',
                     iconCls: 'home',
                     html: 'Welcome to sencha touch'
                  }]
               });
            }
         });
      </script>
   </head>
</html>

This will produce following result −

IOS Classic Theme

Consider your very first Hello World application. Remove the following CSS from the application −

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css

Add the following CSS to use Windows theme −

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/cupertino-classic.css

To see the effect, try the following program −

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/cupertino-classic.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.application({
            name: 'Sencha',
            launch: function() {
               Ext.create("Ext.tab.Panel", {
                  fullscreen: true,
                  items: [{
                     title: 'Home',
                     iconCls: 'home',
                     html: 'Welcome to sencha touch'
                  }]
               });
            }
         });
      </script>
   </head>
</html>

This will produce following result −

Android Theme

Consider your very first Hello World application. Remove the following CSS from the application.

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css

Add the following CSS to use Windows theme.

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/mountainview.css

To see the effect, try the following program −

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/mountainview.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.application({
            name: 'Sencha',
            launch: function() {
               Ext.create("Ext.tab.Panel", {
                  fullscreen: true,
                  items: [{
                     title: 'Home',
                     iconCls: 'home',
                     html: 'Welcome to sencha touch'
                  }]
               });
            }
         });
      </script>
   </head>
</html>

This will produce following result −

BlackBerry Theme

Consider your very first Hello World application. Remove the following CSS from the application.

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css

Add the following CSS to use Windows theme.

https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/bb10.css

To see the effect, try the following program −

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/bb10.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.application({
            name: 'Sencha',
            launch: function() {
               Ext.create("Ext.tab.Panel", {
                  fullscreen: true,
                  items: [{
                     title: 'Home',
                     iconCls: 'home',
                     html: 'Welcome to sencha touch'
                  }]
               });
            }
         });
      </script>
   </head>
</html>

This will produce following result −

Sencha Touch - Device Profile

In today's world of technologies, we have multiple devices such as mobile, tablet, desktop, and laptop with different screen sizes. Hence, there is a need to develop applications, which are accessible from all the devices with good look and feel. However, to develop different code for different devices is very time consuming and costly.

Sencha Touch helps us in this regard, by offering a device profile feature. Based on the active profile, the different dependencies will be run and applicable.

We can declare device profile while writing an application code. We can have multiple devices as −

Ext.application({
   name: 'MyApp',
   profiles: ['Phone', 'Tablet']
});

Once it is done, the profiles will be loaded as −

  • MyApp.profiles.Phone.js
  • MyApp.profiles.Tablet.js

Writing a simple phone profile

Ext.define('Mail.profile.Phone', {
   extend: 'Ext.app.Profile',

   config: {
      name: 'Phone',
      views: ['phoneView']
   },

   isActive: function() {
      return Ext.os.is('Phone');
   }
});

Writing a simple tablet profile

Ext.define('Mail.profile.Tablet', {
   extend: 'Ext.app.Profile',

   config: {
      name: 'Tablet',
      views: ['tableView']
   },

   isActive: function() {
      return Ext.os.is('Tablet');
   }
});

As we can see in profile, we have isActive function which determines if the particular device is active. If the device is active, the corresponding dependencies will be loaded and instantiated.

As mentioned in the above example, if we are using phone device then phone profile's isActive function will return true and the dependencies related to the phone device will be loaded; here phoneView will be loaded. If the device is a tablet then phone profile's isActive function will return false and tablet profile's isActive function will return true and dependency tabletView will be loaded.

Launch Process

One more point to be noticed here is when we have profiles in the application, then the loading and instantiation of application code will be in the following order −

  • Controllers are instantiated first and each controller's init function will be loaded.
  • Profile's launch function will be called.
  • Application's launch function will be called.

Both profile and application's launch functions are optional, so if we do not define any one of them they will not get called.

Take a look at the following code to check where and how the different launch and init functions can be defined.

Controller's init function

Ext.define('MyApp.controller.Main', {
   extend: 'Ext.app.Controller',
   
   init : function (){
      Ext.Msg.alert('Controller's init method');
   },
   
   config: {
      refs: {
         tab: '#divId
     }
   }
});

Profile's launch function

Ext.define('Mail.profile.Tablet', {
   extend: 'Ext.app.Profile',

   config: {
      name: 'Tablet', views: ['tableView']
   },

   isActive: function() {
      return Ext.os.is('Tablet');
   }
   launch : function() {
      Ext.Msg.alert('profile's launch function');
   }
});

Application's launch function

Ext.application({
   name: 'Sencha', launch: function() {
      Ext.Msg.alert(Application's launch function);
   }
});

Sencha Touch - Dependencies

There are certain ways defined in Sencha Touch to declare dependencies, one within the application and the other inside the classes.

Let’s take a look at the different ways to define dependencies.

Application Level Dependencies

Here, we declare all the dependencies when we create Ext.application.

Ext.application({
   name: 'MyApp',
   views: ['StudentsView'],
   models: ['StudentsModel'],
   controllers: ['StudentsController'],
   stores: ['StudentsStore'],
   profiles: ['Phone', 'Tablet']
});

Now, when the application gets loaded, all the dependencies will be loaded at the same time. The path of the other files will be −

  • MyApp.views.StudentsView
  • MyApp.models.StudentsModel
  • MyApp.stores.StudentsStore etc.

The above way of declaration not only loads the file, it also decides which profile it should keep as active. After loading the controller, it makes sure to instantiate it. Once the stores are loaded, it instantiates them and provides one id if not already given.

Profile-specific Dependencies

When we are using profiles in an application, there may be possibilities that few functionalities are only required for some specific profile.

Profile specific dependencies are declared in the profiles itself instead of the application level declaration.

Ext.define('MyApp.profile.Tablet', {
   extend: 'Ext.app.Profile', config: {
      views: ['StudentView'], controllers: ['StudentController'], models: ['StudentModel']
   }
});

Dependencies get loaded irrespective of the profile being active or not. However, based on the active profile, further processing such as instantiating controller and stores happens.

Nested Dependencies

When we have larger application we have multiple controllers, models, views, and stores.

It is always good to keep modularity in larger applications. For that, we can define subfolders and while declaring dependencies we can use subfolder name to declare.

Ext.application({
   name: 'MyApp',
   controllers: ['Controller', 'nested.NewController'],
   views: ['class.Cview', 'SView']
});

In the above case, following files will be loaded −

  • MyApp.controllers.Controller
  • MyApp.controllers.nested.NewController
  • MyApp.Views.Sview
  • MyApp.Views.class.Cview

External Dependencies

We can specify the dependencies outside the application by giving fully qualified names of the classes as −

Ext.Loader.setPath({
   'Class': 'Class'
});

Ext.application({
   views: ['Class.view.LoginForm', 'Welcome'],
   controllers: ['Class.controller.Sessions', 'Main'],
   models: ['Class.model.User']
});

In the above case, following files will be loaded −

  • Class/view/LoginForm.js
  • Class/controller/Sessions.js
  • Class/model/User.js
  • app/view/Welcome.js
  • app/controller/Main.js

Sencha Touch - Environment Detection

It helps you in identifying which operating system you are using, which browser you are working on, and what are the features available for your environment.

Sencha Touch provides different functions to get information specific to the environment. All the methods mentioned below can be checked in, if the condition is if(Ext.os.is.Windows){} and is based on the condition tasks can be performed.

All the following methods return Boolean value.

Operating System

Ext.os is a class that gives you different methods to know which operating system we are working on.

Sr.No Method & Description
1

Ext.os.is.webOS

This function will return true if you are using webos operating system else it returns false.

2

Ext.os.is.RIMTable

This function will return true if you are using RIMTable operating system else it returns false.

3

Ext.os.is.Linux

This function will return true if you are using Linux operating system else it returns false.

4

Ext.os.is.Windows

This function will return true if you are using windows operating system else it returns false.

5

Ext.os.is.MacOs

This function will return true if you are using Mac operating system else it returns false.

6

Ext.os.is.BlackBerry

This function will return true if you are using BlackBerry operating system else it returns false.

7

Ext.os.is.iOS

This function will return true if you are using IOS operating system else it returns false.

8

Ext.os.is.Android

This function will return true if you are using Android operating system else it returns false.

Device Detection

Sr.No Method & Description
1

Ext.os.is.iPad

This function will return true if you are using iPad else it returns false.

2

Ext.os.is.iPhone

This function will return true if you are using iPhone else it returns false.

3

Ext.os.is.iPod

This function will return true if you are using iPod else it returns false.

Version of Operating System

Sr.No Method & Description
1

Ext.os.name

It returns the name of the operating system.

2

Ext.os.version.version

It gives the version of operating system we are using.

Browser Detection

Sr.No Method & Description
1

Ext.browser.is.IE

This function returns true if we are using Internet explorer browser else it returns false.

2

Ext.browser.is.FF

This function returns true if we are using FireFox browser else it returns false.

3

Ext.browser.is.Chrome

This function returns true if we are using Chrome browser else it returns false.

4

Ext.browser.is.Opera

This function returns true if we are using Opera browser else it returns false.
5

Ext.browser.is.Safari

This function returns true if we are using Safari browser else it returns false.

This function Ext.browser provides various other functions −

Sr.No Method & Description
1

Ext.browser.userAgent

It returns the current userAgent.

2

Ext.browser.isSecure

It returns true if the current page is using SSL.

3

Ext.browser.isStrict

It returns true if the browser is in strict mode.

4

Ext.browser.engineName

It returns the browser engine name (WebKit, Gecko, Presto, Trident and Other).

5

Ext.browser.engineVersion

It returns the version of the browser engine.

Features

Ext.feature.has is to check if the browser has following feature or not.

Sr.No Method & Description
1

Ext.feature.has.Audio

This method returns true if browser supports audio tag feature of html5.

2

Ext.feature.has.Canvas

This method returns true if browser supports canvas tag feature of html5.

3

Ext.feature.has.classList

This method returns true if browser supports classlist feature of html5 which is used to add, remove and toggle css classes for the html element.

4

Ext.feature.has.Css3dTransforms

This method returns true if browser supports Css 3d Transform feature of css3.

5

Ext.feature.has.CssAnimations

This method returns true if browser supports animations of css3.

6

Ext.feature.has.CssTransforms

This method returns true if browser supports Css transform feature of css3.

7

Ext.feature.has.CssTransitions

This method returns true if browser supports transition feature of css3.

8

Ext.feature.has.DeviceMotion

This method returns true if browser supports the device motion feature.

9

Ext.feature.has.Geolocation

This method returns true if browser supports the Geolocation feature of html5.

10

Ext.feature.has.History

This method returns true if browser Supports history feature of html.

11

Ext.feature.has.Orientation

This method returns true if browser can detect which the device orientation.

12

Ext.feature.has.OrientationChange

This method returns true if browser can detect change in Orientation of the device.

13

Ext.feature.has.Range

Range is a type of html input tag for range slider element so if browser supports slider this function returns true.

14

Ext.feature.has.SqlDatabase

Web sql database is a web page api for storing data n database on which we can perform query operations. This method returns true if browser supports web Sql Database.

15

Ext.feature.has.Svg

Svg stands for Scalable Vector Graphics this method returns true if browser supports html 5's svg feature.

16

Ext.feature.has.Touch

This method returns true if browser has Touch feature.

17

Ext.feature.has.Video

This method returns true if browser supports html 5 video tags.

18

Ext.feature.has.Vml

Vml stands for vector markup language which is an xml based markup language. So this method returns true if browser has supports vml.

19

Ext.feature.has.WebSockets

Web socket is basically a communication protocol for computers which supports two communication between clients and server. This method returns true if browser Supports WebSockets else it returns false.

Sencha Touch - Events

Events are something which get fired when something happens to the class. For example, when a button is getting clicked or before/after an element is rendered.

Methods of Writing Events

Following are the methods of writing events.

  • Built-in events using listeners.
  • Attaching events later
  • Custom events

Built-in Events Using Listeners

Sencha Touch provides listener property for writing events and custom events in Sencha Touch files.

Writing listener in Sencha Touch

We will add the listener in the previous program itself by adding listen property to the panel, shown as follows −

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.application({
            name: 'Sencha', launch: function() {
               Ext.create('Ext.Panel', {
                  html: 'My Panel', fullscreen: true, listeners: {
                     painted: function() {
                        Ext.Msg.alert('I was painted to the screen');
                     }
                  }
               });
            }
         });
      </script> 
   </head>
</html>

This will produce following result −

This way we can also write multiple events in listeners property.

Multiple events in the same listener

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">   
         Ext.application({
            name: 'Sencha',
            launch: function() {
               var myButton = Ext.Viewport.add({
                  xtype: 'button',
                  centered: true,
                  text: 'Click me'
               });

               myButton.on({
                  tap: function() {
                     var randomWidth = 100 + Math.round(Math.random() * 200);
                     this.setWidth(randomWidth);
                  },
                  widthchange: function(button, newWidth, oldWidth) {
                     alert('My width changed from ' + oldWidth + ' to ' + newWidth);
                  }
               });
            }
         });       
      </script> 
   </head>
</html>

It will produce the following result −

Attaching event later

In the previous method of writing events, we have written events in listeners at the time of creating elements.

The other way to attach events is as follows −

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.application({
            name: 'Sencha',
            launch: function() {
               var myButton = Ext.Viewport.add({
                  xtype: 'button',
                  centered: true,
                  text: 'Click me'
               });
               
               myButton.on('tap', function() {
                  alert("Event listener attached by .on");
               });
            }
         });
      </script> 
   </head>
</html>

It will produce the following result −

Custom events

We can write custom events in Sencha Touch and fire the events with fireEvent method. Following example explains how to write custom events.

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.application({
            name: 'Sencha',
            launch: function() {
               var myButton = Ext.Viewport.add({
                  xtype: 'button',
                  centered: true,
                  text: "Just wait 5 seconds",

                  listeners: {
                     myEvent: function(button, points) {
                        alert('myEvent was fired! You score ' + points + ' points');
                     }
                  }
               });

               Ext.defer(function() {
                  var number = Math.ceil(Math.random() * 100);
                  myButton.fireEvent('myEvent', myButton, number);
               }, 5000);
            }
         });
      </script> 
   </head>
</html>

Once the page is loaded and the document is ready, the UI page with button will appear and as we are firing an event after 5 seconds, once the document is ready the alert box will appear after 5 seconds.

Here we have written the custom event 'myEvent' and we are firing events as button.fireEvent(eventName);

Sencha Touch - Layout

Layout is the way the elements are arranged in a container. That could be horizontal, vertical, or any other. Sencha Touch has different layouts defined in its library though we can always write custom layouts as well.

Sr.No. Layout & Description
1 hBox

This layout allows the element to be distributed in a horizontal manner.

2 vBox

This layout allows the element to be distributed in a vertical manner. This is one of the commonly used layout.

3 Fit

In this layout, the container is filled with a single panel and when there is no specific requirement related to the layout, then this layout is used.

4 Card(TabPanel)

This layout arranges different components in tab fashion. Tabs will be displayed on top of the container. Every time only one tab is visible and each tab is considered as a different component.

Sencha Touch - History Support

Sencha Touch comes with full history support and deep linking facilities.

It has the simplest back button functionality, which helps the user navigate between the screens, without even refreshing the page or application.

It also provides routes functionality, which helps the user navigate to any URL. Based on the URL provided in the browser window, it calls specific functions to perform a specific task.

Look at the following example for back button functionality.

This example shows the nested list which is nothing but a list inside a list, so when you click any of the list items, it opens another list and a back button appears on top of the screen.

For complete code base, you can check Nested List under view component section.

Routing

Simplest example of routes

Ext.define('MyApp.controller.Main', {
   extend: 'Ext.app.Controller',

   config: {
      routes: {
         login: 'showLogin',
		 'user/:id': 'userId'
      }
   },

   showLogin: function() {
      Ext.Msg.alert('This is the login page');
   },
   userId: function(id) {
      Ext.Msg.alert('This is the login page specific to the used Id provided');
   }
});

In the above example if browser URL is https://myApp.com/#login then the function showLogin will be called.

We can provide parameters in the URL and based on the specific parameter the function can get called. For example If the URL is https://myApp.com/#user/3 then the another function userId will be called and the specific ID can be used inside the functions.

Advance routing

Sometime we have advance parameters which includes comma, blank space and special characters etc. for this if we use the above way of writing routes then it will not work. To solve this problem Sencha touch provides conditional routing where we can specify condition of what type of data the parameter should accept.

Ext.define('MyApp.controller.Main', {
   extend: 'Ext.app.Controller', config: {
      routes: {
         login/:id: {
            action: showLogin, conditions: {':id: "[0-9a-zA-Z.]+" }      
         }
      },

      showLogin: function() {
         Ext.Msg.alert('This is the login page with specific id which matches criteria');
      }     
   }
});

So as in the above example we have given regex in the condition which clearly states what type of data should be allowed as URL parameter.

Sharing same URL across different device profiles

As Sencha touch provides device profile so the same application code can be used across multiple devices there may be possibilities that different profiles may have different functionality for the same URL.

To resolve this issue Sencha touch gives us freedom to write routing in the main controller and the called function to be written in the all the profile with their profile specific ones.

Ext.define('MyApp.controller.Main', {
   extend: 'Ext.app.Controller', config: {
      routes: {
         login: 'showLogin'
      }
   },
});
// For phone profile
Ext.define('MyApp.controller.phone.Main, {
   extend: 'MyApp.controller.Main, showLogin: function() {
      Ext.Msg.alert('This is the login page for mobile phone profile');
   }
});
// For tablet profile
Ext.define('MyApp.controller.tablet.Main, {
   extend: 'MyApp.controller.Main,showLogin: function() {
      Ext.Msg.alert('This is the login page for tablet profile');
   }
});

As example shows we have one main controller which has showLogin function and we have two different profiles(Phone/ Tablet). Both the profile has showLogin function with different code specific to the profile.

This way we can share same URL across multiple profile devices with their specific functionalities.

Sencha Touch - Upload & Download

Sencha Touch provides XHR2 configuration to work with Ajax and Ajax2 development.

XHR2 is xmlHttpRequest level 2, which used to request data from the server. For any web application, data resides at the server and once the page is loaded, the data should be accessed from the server with the help of Ajax requests.

XHR2 in Sencha Touch provides the progress bar feature, which shows the user the amount of data transferred for a particular request. XHR2 is newly added so we need to check if the browser supports it or not.

Following is the function to check whether the browser supports XHR2 −

if (Ext.feature.has.XHR2) {
   // Here we can write functionality to work if browser supports XHR2 
}  

We can even check if the progressive upload with XHR2 is supported by the browser or not.

if (Ext.feature.has.XHRUploadProgress) {
   // Here we can write functionality to work if browser supports progressive uploads
}

Various new XHR2 features are included in Sencha Touch.

Sr.No Features & Description
1

XHR2: true

This is used to enable and disable XHR2 functionality in the application.

2

Ext.field.File

New file field is added to give more cality about the type of field.

3

Ext.field.FileInput

This to provide FileInput.

4

Ext.progressIndicator

This is to provide exact percentage of data transferred in terms of progress bar.

5

xtype: fileinput

To create instance of fileInput class.

6

xtype: filefield

To create instance of file class.

7

responseType : value

This parameter allows various types of responses as text, document, blob etc.

Following are the examples to send simple ajax request with and without parameter and uploading files using ajax.

Simple Ajax request without parameters - Success

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.setup({
            requires: [ 'Ext.Panel', 'Ext.Button', 'Ext.form.Panel'], onReady: function() {
               var request = {
                  url: 'https://www.yoursite.com/sencha_touch/index.htm',
                  method: 'POST',
                  xhr2: true,
                  success: function(response) {
                     Ext.Msg.alert('Ajax call successful');
                  },
                  failure: function(response) {
                     Ext.Msg.alert('Ajax call failed');
                  }
               };
               Ext.Viewport.add({
                  xtype:"panel",
                  layout:"vbox",
                  fullscreen:true,
                  items: [
                     {
                        xtype:"button",
                        text: "Ajax",
                        ui: 'confirm',
                        handler: function(){
                           Ext.Ajax.request(request);
                        }
                     }
                  ]
               });
            }
         });
      </script>
   </head>
   <body>
   </body>
</html>

It will produce the following result −

The above example shows the success ajax call as the URL mentioned is correct. In this example, we are not passing any parameter, it’s just a simple ajax request which hits the URL mentioned.

If you are using the chrome browser in the developer tool, navigate to the network section, you can see the request which is being sent and the response which we get.

Simple Ajax request without parameters - Failure

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.setup({
            requires: [
               'Ext.Panel',
               'Ext.Button',
               'Ext.form.Panel'
            ],
            onReady: function() {
               var request = {
                  url: 'https://www.yoursite.com/sencha_touch/indexx.htm',
                  method: 'POST',
                  xhr2: true,
                  success: function(response) {
                     Ext.Msg.alert('Ajax call successful');
                  },
                  failure: function(response) {
                     Ext.Msg.alert('Ajax call failed');
                  }
               };
               Ext.Viewport.add({
                  xtype:"panel",
                  layout:"vbox",
                  fullscreen:true,
                  items: [
                     {
                        xtype:"button",
                        text: "Ajax",
                        ui: 'confirm',
                        handler: function(){
                           Ext.Ajax.request(request);
                        }
                     }
                  ]
               });
            }
         });
      </script>
   </head>
   <body>
   </body>
</html>

It will produce the following result −

In the above example, just to show how ajax failure works we have mentioned the wrong URL. Compare this and the previous example, you will find the difference.

Sending parameters in Ajax request

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.setup({
            requires: [
               'Ext.Panel',
               'Ext.Button',
               'Ext.form.Panel'
            ],

            onReady: function() {
               var formData = new FormData();
               formData.append("firstName", "Hi");
               formData.append("lastName", "Reader");

               // Request will be sent as part of the payload instead of standard post data
               var request = {
                  url: 'https://www.yoursite.com/sencha_touch/sencha_json.php',
                  method: 'POST',
                  xhr2: true,
                  data: formData,
                  success: function(response) {
                     var out = Ext.getCmp("output");
                     response = Ext.JSON.decode(response.responseText, true);
                     Ext.Msg.alert(response.message);
                  },
                  failure: function(response) {
                     var out = Ext.getCmp("output");
                     Ext.Msg.alert('Ajax failed!');
                  }
               };

               Ext.Viewport.add({
                  xtype:"panel",
                  layout:"vbox",
                  fullscreen:true,
                  items: [
                     {
                        xtype:"button",
                        text: "Ajax",
                        ui: 'confirm',
                        handler: function(){
                           Ext.Ajax.request(request);
                        }
                     }
                  ]
               });
            }
         });      
      </script>
   </head>
   <body>
   </body>
</html>

It will produce the following result −

In this example, we are passing parameters with the ajax using data property of ajax call.

Uploading files using Ajax

Live Demo

<!DOCTYPE html>
<html>
   <head>
      <link href = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/resources/css/sencha-touch.css" rel = "stylesheet" />
      <script type = "text/javascript" src = "https://cdn.sencha.com/touch/sencha-touch-2.4.2/sencha-touch-all.js"></script>
      <script type = "text/javascript">
         Ext.setup({
            requires: [
               'Ext.Panel',
               'Ext.MessageBox',
               'Ext.Button',
               'Ext.ProgressIndicator',
               'Ext.form.Panel',
               'Ext.field.FileInput'
            ],

            onReady: function() {
               var progressIndicator = Ext.create("Ext.ProgressIndicator", {
                  loadingText: "Uploading: {percent}%"
               });

               var request = {
                  url: 'https://www.yoursite.com/sencha_touch/sencha_json.php',
                  method: 'POST',
                  xhr2: true,
                  progress:progressIndicator,
                  success: function(response) {
                     Ext.Msg.alert('File uploaded successfully.');
                  },
                  failure: function(response) {
                     Ext.Msg.alert('File upload failed.');
                  }
               };

               Ext.Viewport.add(progressIndicator);
               Ext.Viewport.add({
                  xtype:"panel",
                  layout:"vbox",
                  fullscreen:true,
                  items: [
                     {
                        xtype:"fileinput",
                        accept:"image/jpeg"
                     },
                     {
                        xtype:"button",
                        text: "Upload",
                        ui: 'confirm',
                        handler: function(){
                           var input = Ext.Viewport.down("fileinput").input;
                           var files = input.dom.files;
                           if (files.length) {
                              request.binaryData = files[0];
                              Ext.Ajax.request(request);
                           }else {
                              Ext.Msg.alert("Please Select a JPG");
                           }
                        }
                     }
                  ]
               });
            }
         });
      </script>
   </head>
   <body>
   </body>
</html>

It will produce the following result −

This example shows how to upload data using ajax call. In this example, we are using the progress bar indicator to show the progress while uploading the file.

Sencha Touch - View Components

Sencha Touch provides various UI components, which can be customized according to requirements.

Sr.N0. Component & Description
1 Carousel

This UI component is used to display Carousel.

2 List

This UI component is used to display lists.

3 Nested List

This UI component is used to display nested list.

4 Form

This UI component is used to display Forms.

5 Chart

This UI component is used to display different types of charts.

6 Floating Component

This UI component is used to display floating component.

7 Tab Panel

This UI component is used to display Tab panel view.

8 Navigation View

This UI component is used to display navigation view.

9 Action Menu

This UI component is used to display action menu bar.

10 Data View

This UI component is used to display data view.

11 Map

This UI component is used to display google map.

Sencha Touch - Packaging

Sencha Touch comes with native packaging features.

Following are the links for native packaging concepts of Sencha Touch.

Sr.No. Concept & Description Link
1 Native iOS provisioning
2 Native APIs

Sencha Touch - Best Practice

Basic JavaScript best practice

It is a good practice to keep all JavaScript-related code in a separate js (external JS) file, instead of writing it in the <script> tag under the head section or inline JavaScript in the document body.

Always perform a null check before the element is being used in further logic.

Always follow the naming convention, as it makes the code easy to understand by any other programmer.

To make the code easily understandable, it is always preferred to write comments for JS methods with clear logic behind what a function does.

Best practice specific to Sencha Touch

Use Sencha Touch recommended folder structure, which will be helpful during JS compression or minification.

It is highly recommended to use the listener (onclick/onblur, etc.) in the controller instead of writing it in the html page itself.

Do not create the store instance, when the store is being called from the view.

When we create an instance of a store, we should always destroy it, as it impacts the performance.

While using Sencha Touch, do not specify any other simple JavaScript file. Use all the functions from Ext classes (mentioned in controller or utils).

When the model mapping and the name are same, then do not specify mapping. Only name will solve the purpose.

Do not use unnecessary properties in view. Use only the property which is required and it value which is different from the default value.

Sass Tutorial

posted on June 9, 2021

tags:

What is SASS?

SASS (Syntactically Awesome Stylesheet) is a CSS pre-processor, which helps to reduce repetition with CSS and saves time. It is more stable and powerful CSS extension language that describes the style of a document cleanly and structurally.

It was initially designed by Hampton Catlin and developed by Natalie Weizenbaum in 2006. Later, Weizenbaum and Chris Eppstein used its initial version to extend the Sass with SassScript.

Why to Use SASS?

  • It is a pre-processing language which provides indented syntax (its own syntax) for CSS.

  • It provides some features, which are used for creating stylesheets that allows writing code more efficiently and is easy to maintain.

  • It is a super set of CSS, which means it contains all the features of CSS and is an open source pre-processor, coded in Ruby.

  • It provides the document style in a good, structured format than flat CSS. It uses re-usable methods, logic statements and some of the built-in functions such as color manipulation, mathematics and parameter lists.

Features of SASS

  • It is more stable, powerful, and compatible with versions of CSS.

  • It is a super set of CSS and is based on JavaScript.

  • It is known as syntactic sugar for CSS, which means it makes easier way for user to read or express the things more clearly.

  • It uses its own syntax and compiles to readable CSS.

  • You can easily write CSS in less code within less time.

  • It is an open source pre-processor, which is interpreted into CSS.

Advantages of SASS

  • It allows writing clean CSS in a programming construct.

  • It helps in writing CSS quickly.

  • It is a superset of CSS, which helps designers and developers work more efficiently and quickly.

  • As Sass is compatible with all versions of CSS, we can use any available CSS libraries.

  • It is possible to use nested syntax and useful functions such as color manipulation, mathematics and other values.

Disadvantages of SASS

  • It takes time for a developer to learn new features present in this pre-processor.

  • If many people are working on the same site, then should use the same preprocessor. Some people use Sass and some people use CSS to edit the files directly. Therefore, it becomes difficult to work on the site.

  • There are chances of losing benefits of browser's built-in element inspector.

Sass - Installation

In this chapter, we will learn the step-by-step procedure to install Ruby, which is used for executing the SASS files.

System Requirements for SASS

  • Operating System − Cross-platform

  • Browser Support − IE (Internet Explorer 8+), Firefox, Google Chrome, Safari, Opera

  • Programming Language − Ruby

Installation of Ruby

Step 1 − Open the link https://www.ruby-lang.org/en/downloads/, you will see a screen as shown below −

SASS Installation

Download the Current stable version of the zip file.

Step 2 − Next, run the setup to install Ruby on the System.

Step 3 − Next, add Ruby bin folder to your PATH User Variable and System Variable to work with gem command.

Path User Variable

  • Right Click the My Computer icon.

  • Select Properties.

  • Next, click the Advanced tab and click Environment Variables.

SASS Installation

In the Environment Variables window, double click the PATH as shown in the screenshot given below −

SASS Installation

You will get an Edit User Variable box as shown. Add ruby bin folder path in the Variable value field as C:Rubyin. If path is already set for other files, then put semicolon after that and add the Ruby folder path as shown below.

SASS Installation

Click the OK button.

System Variable

  • Click the New button.

SASS Installation

Next, the New System Variable block is displayed as shown below.

SASS Installation

  • Enter RubyOpt in the Variable name field and rubygems in the Variable value field. After writing the Variable name and value, click the OK button.

Step 4 − Open the command prompt in your system and enter the following line −

gem install sass

Step 5 − Next, you will see the following screen after installing SASS successfully.

SASS Installation

Example

The following is a simple example of SASS.

<html>
   <head>
      <title> Import example of sass</title>
      <link rel = "stylesheet" type = "text/css" href = "style.css"/>
   </head>

   <body>
      <h1>Simple Example</h1>
      <h3>Welcome to Yoursite</h3>
   </body>
</html>

Now, we will create file as style.scss, which is quite similar to CSS and the only one difference is that it will be saved with .scss extension. Both, .htm and .scss files should be created inside the folder ruby. You can save your .scss file in the folder rubylibsass (before this process, create a folder as sass in lib directory).

h1{
   color: #AF80ED;
}

h3{
   color: #DE5E85;
}

You can tell SASS to watch the file and update the CSS whenever SASS file changes, by using the following command −

sass --watch C:
ubylibsassstyle.scss:style.css

SASS Installation

When you run the above command, it will create the style.css file automatically. Whenever you change the SCSS file, the style.css file will be updated automatically.

The style.css file will have the following code when you run the above given command −

style.css

h1 {
   color: #AF80ED;
}
h3 {
   color: #DE5E85;
}

Let us carry out the following steps to see how the above given code works −

  • Save the above given code in hello.html file.

  • Open this HTML file in a browser.

SASS Installation

Sass - Syntax

In this chapter, we will study about SASS Syntax. SASS supports two syntaxes namely SCSS and Indented syntax.

  • The SCSS (Sassy CSS) is an extension of CSS syntax. This means every valid CSS is a valid SCSS as well. SCSS makes much easier to maintain large stylesheets and can recognize vendor specific syntax, Many CSS and SCSS files use the extension .scss.

  • Indented − This is older syntax and sometimes just called as SASS. Using this form of syntax, CSS can be written concisely. SASS files use the extension .sass.

SASS Indented Syntax

SASS Indented syntax or just SASS is an alternative to CSS based SCSS syntax.

  • It uses indentation rather than { and } to delimit blocks.

  • To separate statements, it uses newlines instead of semicolons(;).

  • Property declaration and selectors must be placed on its own line and statements within { and } must be placed on new line and indented.

For instance, consider the following SCSS code −

.myclass {
   color = red;
   font-size = 0.2em;
}

The indented syntax is an older syntax, which is not recommended for use in new Sass files. If you use this file, it will display error in the CSS file as we have used = instead of for setting properties and variables.

Compile the above given code using the following command −

sass --watch C:
ubylibsassstyle.scss:style.css

Next, run the above command; it will display an error in style.css file as shown below −

Error: Invalid CSS after "  color = red": expected "{", was ";"
      on line 2 of C:
ubylibsassstyle17.scss

1:.myclass {
2:   color = red;
3:   font-size = 0.2em;
4:}

Syntax Differences of SASS

Most CSS and SCSS syntaxes work perfectly in SASS. However, there are some differences, which are explained in the following sections −

Property Syntax

CSS properties can be declared in two ways −

  • Properties can be declared similar to CSS but without semicolon(;).

  • colon(:) will be prefixed to every property name.

For instance, you can write as −

.myclass
   :color red
   :font-size 0.2em

Both the above ways (properties declaration without semicolon and colon prefixed to property name) can be used, by default. However, only one property syntax is allowed to specify when you use the :property_syntax option.

Multiline Selectors

In Indented syntax, selectors can be placed on a newline whenever they appear after commas.

Example

The following example describes the use of multiline selectors in the SCSS file −

<html>
   <head>
      <title>Multiline Selectors</title>
      <link rel = "stylesheet" type = "text/css" href = "style.css" />
      <link rel = "stylesheet" href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
      <script src = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
   </head>
   
   <body>
      <h2>Example using Multiline Selectors</h2 >
      <p class = "class1">Welcome to yoursite!!!</p>
      <p class = "class2">SASS stands for Syntactically Awesome Stylesheet...</p>
   </body>
</html>

Next, create file style.scss. Note the .scss extension.

style.scss

.class1,
.class2{
   color:red;
}

You can tell SASS to watch the file and update the CSS whenever SASS file changes, by using the following command −

sass --watch C:
ubylibsassstyle.scss:style.css

Next, execute the above given command, it will create the style.css file automatically with the following code −

The generated style.css is as shown below −

style.css

.class1,
.class2 {
   color: red;
}

Output

Let us carry out the following steps to see how the above given code works −

  • Save the above given html code in multiline_selectors.html file.

  • Open this HTML file in a browser, an output is displayed as shown below.

Sass Syntax

Comments

Comments take up an entire line and enclose all the text nested under them. They are line-based in indented syntax. For more information about comments, refer this link.

@import

In SASS the @import directive can be written with/without quotes. Unlike in SCSS, they must be used with quotes.

For instance, in SCSS the @import directive can be used as −

@import "themes/blackforest";
@import "style.sass";

This can be written in SASS as −

@import themes/blackforest
@import fontstyle.sass

Mixin Directives

SASS supports shorthand for directives like @mixin and @include. Instead of @mixin and @include you can use = and + characters, which require less typing and makes your code simpler, and easier to read.

For instance, you can write the mixin directives as −

=myclass
   font-size: 12px;
p
   +myclass

The above given code is the same as −

@mixin myclass
   font-size: 12px;
p
   @include myclass

Deprecated Syntax

SASS supports the use of some old syntax. However, using this syntax in SASS is not recommended. Warning will be displayed if you use this syntax and it is removed in later versions. Some of the old syntaxes are shown in the following table.

S. No. Operator & Description
1

=

It was used instead of : when setting variables and properties to values of SassScript.

2

||=

It was used instead of : whenever you are assigning default value of a variable.

3

!

Instead of $, ! was used as variable prefix. Functionality will not be changed when it is used instead of $.

Using Sass

SASS is more powerful and stable that provides power to the basic language by using extension of CSS. You can use SASS in three different ways −

  • As a command line tool
  • As a Ruby module
  • As a plugin for Rack enable framework

If you are using SASS on windows, then you need to install Ruby first. For more information about installing Ruby, refer the SASS Installation chapter.

The following table shows the commands, which are used for executing the SASS code −

S. No. Command & Description
1

sass input.scss output.css

It is used to run the SASS code from the command line.

2

sass --watch input.scss:output.css

It informs SASS to watch the file and update the CSS whenever SASS file changes.

3

sass --watch app/sass:public/stylesheets

It is used to watch the entire directory, if SASS contains many files in a directory.

Rack/Rails/Merb Plugin

Rack is a web server interface, which is used for developing web applications in Ruby. For information about Rack, just visit this link.

You can enable the SASS in the Rails 3 version using the environment.rb file present under the config folder. Enable the SASS for the Rails 3 using the following code −

config.gem "sass"

You can use the following line to the Gemfile for the Rails 3(and above version), as −

gem "sass"

Rails is an open-source web framework that uses web standards such as JSON, HTML, CSS and JavaScript for displaying user interface. To work with Rails, you need to have a basic knowledge of Ruby and object-oriented programming. Learn more about on Rails framework here.

If you want to enable the SASS in Rack application, add the following lines to the config.ru file, which is present in the app's root directory −

require 'sass/plugin/rack'
use Sass::Plugin::Rack

Merb is a web application framework, which provides speed and modularity to Rails. To know more about Merb, just open this link.

You can enable the SASS in Merb by adding the following line to the config/dependencies.rb file −

dependency "merb-haml"

Caching

SASS caches documents such as templates and partials, which can be reused without parsing them unless they have changed. It makes compilation of SASS files faster and works even better when the templates are divided into separate files, which are all imported into one large file. If you delete cached files, they will be generated again when you compile next time.

Options

You can set the options in the environment.rb file of Rails or config.ru file of Rack application by using the following line −

Sass::Plugin.options[:style] = :compact

You can also set options in the init.rb file of Merb by using the following line −

Merb::Plugin.config[:sass][:style] = :compact

There are some options available with SASS and SCSS as described in the table given below −

S. No. Option & Description
1

:style

It displays style of the output.

2

:syntax

You can use indented syntax for sass and CSS extension syntax for scss.

3

:property_syntax

It uses indented syntax to make use of properties. If it is not correct, then it will throw an error. For instance, consider "background: #F5F5F5" in which background is a property name and #F5F5F5 is its property value. You must use colon after the property name.

4

:cache

It speeds up compilation of SASS files. It is set to true by default.

5

:read_cache

It read only SASS files if cache is not set and read_cache is set.

6

:cache_store

It can be used to store and access the cached result by setting it to an instance of Sass::CacheStores::Base.

7

:never_update

It should never update the CSS file if the template files changes. By default it is set to false.

8

:always_update

It should update the CSS file whenever the template files changes.

9

:always_check

It should check for the updates whenever the server starts. It will recompile and overwrite the CSS file, if there is an update in the SASS template file.

10

:poll

It uses polling backend for Sass::Plugin::Compiler#watch (which watches the template and updation of CSS files) by setting it to true.

11

:full_exception

It displays the error description whenever an exception occurs in SASS code within generated CSS file. It displays a line number where an error occurred along with source in the CSS file.

12

:template_location

It provides the path for the template directory in the application.

13

:css_location

It provides the path for the CSS stylesheets in the application.

14

:unix_newlines

It provides Unix style newlines when writing files by setting it to true.

15

:filename

It is name of the filename being displayed and used for reporting errors.

16

:line

It specifies the first line of the SASS template and displays the line numbers for errors.

17

:load_paths

It is used to load the paths for SASS template which are included using @import directive.

18

:filesystem_importer

It is used to import files from file system that uses Sass::Importers::Base sub class to handle string load paths.

19

:sourcemap

It generates source maps which instructs browser to find the SASS styles. It uses three values −

  • :auto − It contains relative URIs. If there is no relative URI, then uses "file:" URI.

  • :file − It uses "file:" URIs, which work locally, not on remote server.

  • :inline − It contains source text in the source map which is used to create large source map files.

20

:line_numbers

It displays the line number for errors reported in the CSS file by setting it to true.

21

:trace_selectors

It helps to trace the selectors of imports and mixins when it is set to true.

22

:debug_info

It provides debug information of SASS file using line number and file when it is set to true.

23

:custom

It makes data available to SASS functions in the separate applications.

24

:quiet

It disables the warnings by setting it to true.

Syntax Selection

You can determine which syntax you are using in the SASS template by using the SASS command line tool. By default, SASS uses indented syntax which is an alternative to CSS based SCSS syntax. You can use the SCSS command line program, which is similar to the SASS program, but by the default, it considers the syntax to be SCSS.

Encodings

SASS uses the character encoding of stylesheets by specifying the following CSS specifications −

  • First, it checks for Unicode byte, next @charset declaration and then Ruby string encoding.

  • Next, if nothing is set, then it considers charset encoding as UTF-8.

  • Determine character encoding explicitly by using @charset declaration. Just use "@charset encoding name" at the beginning of the stylesheet and SASS will assume that this is the given character encoding.

  • If output file of SASS contains non-ASCII characters, then it will use the @charset declaration.

Sass - CSS Extensions

In this chapter, we will study about CSS Extensions. CSS Extensions can be used to enhance the functionality of the web pages. The following table lists down some of the CSS extensions used in SASS −

S. No. CSS Extension & Description
1 Nested Rules

It is a way of combining multiple CSS rules within one another.

2 Referencing Parent Selectors: &

It is the process of selecting parent selector by using the & character.

3 Nested Properties

It allows nesting of properties into other properties which leads to grouping of another related code.

4 Placeholder Selectors

Sass supports placeholder selector using class or id selector by making use of @extend directive.

Sass - Comments

In this chapter, we will study about Sass Comments. Comments are non-executable statements, which are placed in source code. Comments make source code easier to understand. SASS supports two types of comments.

  • Multiline comments − These are written using /* and */. Multiline comments are preserved in CSS output.

  • Single line comments − These are written using // followed by comments. Single line comments are not preserved in CSS output.

Example

The following example demonstrates the use of comments in the SCSS file −

<html>
   <head>
      <title>SASS comments</title>
      <link rel = "stylesheet" type = "text/css" href = "style.css"/>
   </head>

   <body>
      <h1>Welcome to yoursite</h1>
      <a href = "http://www.yoursite.com/">yoursite</a>
   </body>
</html>

Next, create file style.scss.

style.scss

/* This comment is
 * more than one line long
 * since it uses the CSS comment syntax,
 * it will appear in the CSS output. */
body { color: black; }

// These comments are in single line
// They will not appear in the CSS output,
// since they use the single-line comment syntax.
a { color: blue; }

You can tell SASS to watch the file and update the CSS whenever SASS file changes, by using the following command −

sass --watch C:
ubylibsassstyle.scss:style.css

Next, execute the above command, it will create the style.css file automatically with the following code −

style.css

/* This comment is
 * more than one line long
 * since it uses the CSS comment syntax,
 * it will appear in the CSS output. */
body {
   color: black; }

a {
   color: blue; }

Output

Let us carry out the following steps to see how the above given code works −

  • Save the above given html code in sass_comments.html file.

  • Open this HTML file in a browser, an output is displayed as shown below.

Sass Comments

To study about interpolation within multiline comments, click this link.

Sass – Interpolation in Multiline Comments

Description

Interpolation within the multiline comments are resolved in the resulting CSS. You can specify variables or property names within the curly braces.

Syntax

$var : "value";
/* multiline comments #{$var} */

Example

The following example demonstrates the use of interpolation in multiline comments in the SCSS file −

<html>
   <head>
      <title>SASS comments</title>
      <link rel = "stylesheet" type = "text/css" href = "style.css"/>
   </head>

   <body>
      <h1>Welcome to yoursite</h1>
      <p>This is an example for Interpolation in SASS.</p>
   </body>
</html>

Next, create file style.scss.

style.css

$version: "7.8";
/* Framework version for the generated CSS is #{$version}. */

You can tell SASS to watch the file and update the CSS whenever SASS file changes, by using the following command −

sass --watch C:
ubylibsassstyle.scss:style.css

Next, execute the above command; it will create the style.css file automatically with the following code

style.css

/* Framework version for the generated CSS is 7.8. */

Output

Let us carry out the following steps to see how the above given code works −

  • Save the above given html code in sass_comments_interpolation.htm file.

  • Open this HTML file in a browser, an output is displayed as shown below.

Sass Comments

Sass - Script

SASS uses a small set of extensions known as SassScript which can be included in the SASS documents to compute variables from property values and uses properties of variables, arithmetic, and other functions. SassScript can also be used with selectors and property names while using mixins (Mixins allows to re-use CSS styles throughout the stylesheet).

The following table lists some of the CSS extensions used in SASS −

S. No. CSS Extension & Description
1 Interactive Shell

It evaluates SassScript expression using command line.

2 Variables

It represents the data such as numeric values, characters or memory addresses.

3 DataTypes

It declares data type for every data object.

4 Operations

It provides operations such as number, color, string, boolean and list operations.

5 Parentheses

It is pair of signs which are usually marked off by round brackets ( ) or square brackets [].

6 Functions

It supports for the use of functions by providing some keyword arguments.

7 Interpolation

It provides SassScript variables and property names using #{ } syntax.

8 & in SassScript

It allows nesting of properties into another properties which leads to group of another related code.

9 Variable Defaults

It allows nesting of properties into another properties which leads to group of another related code.

Sass - @-Rules and Directives

The following table lists all the rules and directives which you can use in SASS.

S. No. Directives & Description
1 @import

It imports the SASS or SCSS files, it directly takes the filename to import.

2 @media

It sets the style rule to different media types.

3 @extend

@extend directive is used to share rules and relationships between selectors.

4 @at-root

@at-root directive is a collection of nested rules, which is able to make style block at root of the document.

5 @debug

@debug directive detects the errors and displays the SassScript expression values to the standard error output stream.

6 @warn

@warn directive is used to give cautionary advice about the problem; it displays the SassScript expression values to the standard error output stream.

7 @error

@error directive displays the SassScript expression value as fatal error.

Sass - Control Directives & Expressions

In this chapter, we will study about Control Directives & Expressions. Styling based on some conditions or applying the same style many times with variations can be accomplished by using control directives and expressions, which are supported by SassScript. These control directives are advanced options used mainly in mixins. They require considerable flexibility, as they are a part of Compass libraries.

The following table lists the control directives and expressions used in SASS −

S. No. Control Directive & Expression with Description
1 if()

Based on the condition, if() function returns only one result from two possible outcomes.

2 @if

The @if directive accepts SassScript expressions and uses the nested styles whenever the result of the expression is anything other than false or null.

3 @for

The @for directive allows you to generate styles in a loop.

4 @each

In @each directive, a variable is defined which contains the value of each item in a list.

5 @while

It takes SassScript expressions and untill the statement evaluates to false it iteratively outputs nested styles.

Sass - Mixin Directives

Mixins allow creating a group of styles, which are reusable throughout your stylesheet without any need to recreation of non-semantic classes. In CSS, the mixins can store multiple values or parameters and call function; it helps to avoid writing repetitive codes. Mixin names can use underscores and hyphens interchangeably. Following are the directives present in Mixins −

S. No. Directive & Description
1 Defining a Mixin

@mixin directive is used to define the mixin.

2 Including a Mixin

@include directive is used to include the mixins in the document.

3 Arguments

The SassScript values can be taken as arguments in mixins, which is given when mixin is included and available as variable within the mixin.

4 Passing Content Blocks to a Mixin

Block of styles are passed to the mixin.

Sass - Function Directives

In this chapter, we will study about Function Directives. In SASS, you can create your own function and use them in your script context or can be used with any value. Functions are called by using the function name and with any parameters.

Example

The following example demonstrates the use of function directive in the SCSS file −

function_directive.htm

<html>
   <head>
      <title>Nested Rules</title>
      <link rel = "stylesheet" type = "text/css" href = "style.css" />
      <link rel = "stylesheet" href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
      <script src = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
   </head>

   <body>
      <div class = "container" id = "set_width">
         <h2>Example for Function directives</h2>
         <p>SASS stands for Syntactically Awesome Stylesheet. </p>
      </div>
   </body>
</html>

Next, create file style.scss.

style.scss

$first-width: 5px;
$second-width: 5px;

@function adjust_width($n) {
   @return $n * $first-width + ($n - 1) * $second-width;
}

#set_width { padding-left: adjust_width(10); }

You can tell SASS to watch the file and update the CSS whenever SASS file changes, by using the following command −

sass --watch C:
ubylibsassstyle.scss:style.css

Next, execute the above command; it will create the style.css file automatically with the following code −

style.css

#set_width {
   padding-left: 95px; 
}

Output

Let us carry out the following steps to see how the above given code works −

  • Save the above given html code in function_directive.html file.

  • Open this HTML file in a browser, an output is displayed as shown below.

Sass Function Directives

In the output, you can see that the left-padding is being applied.

Just like mixin, function can also access globally defined variables and can also accept parameters. You should call the return value for the function by using @return. We can call the SASS-defined functions by using keyword parameters.

Call the above function as shown below.

#set_width { padding-left: adjust_width($n: 10); }

Naming Conventions

To avoid naming conflicts function names can be prefixed so that they can be easily differentiated. Like mixins, variable arguments are also supported by user-defined functions. Functions and other SASS identifiers can use underscores(_) and hyphens(-) interchangeably.

For example, if a function is defined as adjust_width, it can be used as adjust-width, and vice versa.

Sass - Output Style

In this chapter, we will study about SASS Output Style. The CSS file that the SASS generates consists of default CSS style, which reflects the structure of document. The default CSS styling is good but might not be suitable for all situations; on other hand, SASS supports many other styles.

It supports the following different output styles −

:nested

Nested style is default styling of SASS. This way of styling is very useful when you are dealing with large CSS files. It makes the structure of the file more readable and can be easily understood. Every property takes its own line and indentation of each rule is based on how deeply it is nested.

For instance, we can nest the code in SASS file as shown below −

#first {
   background-color: #00FFFF;
   color: #C0C0C0; 
}

#first p {
   width: 10em; 
}

.highlight {
   text-decoration: underline;
   font-size: 5em;
   background-color: #FFFF00; 
}

:expanded

In expanded type of CSS styling each property and rule has its own line. It takes more space compared to the Nested CSS style. The Rules section consists of properties, which are all intended within the rules, whereas rules does not follow any indentation.

For instance, we can expand the code in the SASS file as shown below −

#first {
   background-color: #00FFFF;
   color: #C0C0C0;
}

#first p {
   width: 10em;
}

.highlight {
   text-decoration: underline;
   font-size: 5em;
   background-color: #FFFF00;
}

:compact

Compact CSS style competitively takes less space than Expanded and Nested. It focuses mainly on selectors rather than its properties. Each selector takes up one line and its properties are also placed in the same line. Nested rules are positioned next to each other without a newline and the separate groups of rules will have new lines between them.

For instance, we can compact the code in the SASS file as shown below −

#first { 
   background-color: #00FFFF; color: #C0C0C0; 
}

#first p { 
   width: 10em; 
}

.highlight { 
   text-decoration: underline; font-size: 5em; background-color: #FFFF00; 
}

:compressed

Compressed CSS style takes the least amount of space compared to all other styles discussed above. It provides whitespaces only to separate selectors and newline at the end of the file. This way of styling is confusing and is not easily readable.

For instance, we can compress the code in SASS file as shown below −

#first { 
   background-color:#00FFFF;color:#C0C0C0
} 

#first p { 
   width:10em 
} 

.highlight { 
   text-decoration:underline;font-size:5em;background-color:#FFFF00 
}

Extending Sass

You can extend the functionality of SASS to provide different types of features and customizations for users. To make use of these features, user should have knowledge of Ruby.

Defining Custom SASS Functions

You can define your own SASS functions while using Ruby API. You can add your custom functions by adding them to Ruby methods as shown in the following code −

module Sass::Script::Functions
   def reverse(string)
      assert_type string, :String
      Sass::Script::Value::String.new(string.value.reverse)
   end
   declare :reverse, [:string]
end

In the code you could see, the Function, declare, specifies the argument names for the function. If it fails then it will not accept any arguments even if the function is working and it also takes arbitrary keyword arguments. You can get Ruby values by using value accessor and access the color objects by using rgb, red, green, or blue.

Cache Stores

SASS stores cache of parsed documents, which can be reused without parsing again. SASS uses :cache_location to write cache files on the file system. It makes compilation of SASS files faster and if you delete cached files, they will be generated again when you compile next time. You can define your own cache store by setting the :cache_store option. This will write cache files on the file system or share cache files to ruby processes or machines. SASS uses instance of subclass of Sass::CacheStores::Base to store and retrieve cache results.

Custom Importers

SASS uses @import to import SCSS and SASS files and passes paths to @import rule to find an appropriate path code for specified paths. SASS importers use file system for loading the code and added to the load using database or different file naming scheme.

Single importer can take single file loading and can be placed in :load_paths array along with the paths of file system. While using @import, SASS looks for loaded paths, which import the path for the importer. When the path is found, the imported file is used. A user can inherit the importers from Sass::Importers::Base.

What language will be most in demand in the web development market in the next 5 years?

posted on June 9, 2021

tags:

I would rank the languages in this order:

1) JavaScript
2) Python
3) Ruby

Here's why...

You could just do Python, but if you have the energy and time, solid knowledge of JavaScript can only help you. It's everywhere and not going away.

As for Ruby, my impression of Ruby developers is that they're generally very smart, careful programmers.

You could say this is silly, but if you step back, you do see a general style that goes with a specific language.

That said, the choice of languages and frameworks when Ruby and ROR came to the party are very different than they are now.

ROR offered a rapid application development (RAD) platform that appealed to developers who had to get things done fast, but also appreciated elegant code.

Ruby experts are doing very well (pay rate and availability of jobs), but if you're just getting started, I wouldn't start with Ruby.

I think JavaScript/Python are a better pair considering the current (and what I imagine to be future) market.

As for choosing a language by hourly rate, be careful there.

I was one of the highest-paid Macintosh C programmers I knew (in about 1994) until the work completely disappeared.

There's a time when companies still have ongoing projects in a language/framework and need resources. When new people aren't learning the language and old people are leaving, supply and demand causes rates to rise. Then the whole market disappears.

Ruby on Rails Tutorial

posted on June 8, 2021

tags:

What is Ruby?

Before we ride on Rails, let us recapitulate a few points of Ruby, which is the base of Rails.

Ruby is the successful combination of −

  • Smalltalk's conceptual elegance,
  • Python's ease of use and learning, and
  • Perl's pragmatism.

Ruby is −

  • A high-level programming language.
  • Interpreted like Perl, Python, Tcl/TK.
  • Object-oriented like Smalltalk, Eiffel, Ada, Java.

Why Ruby?

Ruby originated in Japan and now it is gaining popularity in US and Europe as well. The following factors contribute towards its popularity −

  • Easy to learn
  • Open source (very liberal license)
  • Rich libraries
  • Very easy to extend
  • Truly object-oriented
  • Less coding with fewer bugs
  • Helpful community

Although we have many reasons to use Ruby, there are a few drawbacks as well that you may have to consider before implementing Ruby −

  • Performance Issues − Although it rivals Perl and Python, it is still an interpreted language and we cannot compare it with high-level programming languages like C or C++.

  • Threading model − Ruby does not use native threads. Ruby threads are simulated in the VM rather than running as native OS threads.

Sample Ruby Code

Here is a sample Ruby code to print "Hello Ruby"

# The Hello Class
class Hello
   
   def initialize( name )
      @name = name.capitalize
   end

   def salute
      puts "Hello #{@name}!"
   end
   
end

# Create a new object
h = Hello.new("Ruby")

# Output "Hello Ruby!"
h.salute

Output − This will produce the following result −

Hello Ruby!

Embedded Ruby

Ruby provides a program called ERB (Embedded Ruby), written by Seki Masatoshi. ERB allows you to put Ruby codes inside an HTML file. ERB reads along, word for word, and then at a certain point, when it encounters a Ruby code embedded in the document, it starts executing the Ruby code.

You need to know only two things to prepare an ERB document −

  • If you want some Ruby code executed, enclose it between <% and %>.

  • If you want the result of the code execution to be printed out, as a part of the output, enclose the code between <%= and %>.

Here's an example. Save the code in erbdemo.rb file. Note that a Ruby file will have an extension .rb

<% page_title = "Demonstration of ERB" %>
<% salutation = "Dear programmer," %>

<html>

   <head>
      <title><%= page_title %></title>
   </head>
	
   <body>
      <p><%= salutation %></p>
      <p>This is an example of how ERB fills out a template.</p>
   </body>
	
</html>

Now, run the program using the command-line utility erb.

tp> erb erbdemo.rb

This will produce the following result −

<html>

   <head>
      <title>Demonstration of ERb</title>
   </head>
	
   <body>
      <p>Dear programmer,</p>
      <p>This is an example  of how ERb fills out a template.</p>
   </body>
	
</html>

What is Rails?

  • An extremely productive web-application framework.

  • Written in Ruby by David Heinemeier Hansson.

  • You could develop a web application at least ten times faster with Rails than you could with a typical Java framework.

  • An open source Ruby framework for developing database-backed web applications.

  • Configure your code with Database Schema.

  • No compilation phase required.

Full Stack Framework

  • Includes everything needed to create a database-driven web application, using the Model-View-Controller pattern.

  • Being a full-stack framework means all the layers are built to work seamlessly together with less code.

  • Requires fewer lines of code than other frameworks.

Convention over Configuration

  • Rails shuns configuration files in favor of conventions, reflection, and dynamic runtime extensions.

  • Your application code and your running database already contain everything that Rails needs to know!

Rails Strengths

Rails is packed with features that make you more productive, with many of the following features building on one other.

Metaprogramming

Where other frameworks use extensive code generation from scratch, Rail framework uses Metaprogramming techniques to write programs. Ruby is one of the best languages for Metaprogramming, and Rails uses this capability well. Rails also uses code generation but relies much more on Metaprogramming for the heavy lifting.

Active Record

Rails introduces the Active Record framework, which saves objects into the database. The Rails version of the Active Record discovers the columns in a database schema and automatically attaches them to your domain objects using metaprogramming.

Convention over configuration

Most web development frameworks for .NET or Java force you to write pages of configuration code. If you follow the suggested naming conventions, Rails doesn't need much configuration.

Scaffolding

You often create temporary code in the early stages of development to help get an application up quickly and see how major components work together. Rails automatically creates much of the scaffolding you'll need.

Built-in testing

Rails creates simple automated tests you can then extend. Rails also provides supporting code called harnesses and fixtures that make test cases easier to write and run. Ruby can then execute all your automated tests with the rake utility.

Three environments

Rails gives you three default environments: development, testing, and production. Each behaves slightly differently, making your entire software development cycle easier. For example, Rails creates a fresh copy of the Test database for each test run.

Ruby on Rails - Installation

To develop a web application using Ruby on Rails Framework, you need to install the following software −

  • Ruby
  • The Rails Framework
  • A Web Server
  • A Database System

We assume that you already have installed a Web Server and a Database System on your computer. You can use the WEBrick Web Server, which comes with Ruby. Most websites however use Apache or lightTPD web servers in production.

Rails works with many database systems, including MySQL, PostgreSQL, SQLite, Oracle, DB2 and SQL Server. Please refer to a corresponding Database System Setup manual to set up your database.

Let's look at the installation instructions for Rails on Windows and Linux.

Rails Installation on Windows

Follow the steps given below for installing Ruby on Rails.

Step 1: Check Ruby Version

First, check if you already have Ruby installed. Open the command prompt and type ruby -v. If Ruby responds, and if it shows a version number at or above 2.2.2, then type gem --version. If you don't get an error, skip Install Ruby step. Otherwise, we'll install a fresh Ruby.

Step 2: Install Ruby

If Ruby is not installed, then download an installation package from rubyinstaller.org. Follow the download link, and run the resulting installer. This is an exe file rubyinstaller-2.2.2.x.exe and will be installed in a single click. It's a very small package, and you'll get RubyGems as well along with this package. Please check the Release Notes for more detail.

Ruby Home

Step 3: Install Rails

Install Rails − With Rubygems loaded, you can install all of Rails and its dependencies using the following command through the command line −

C:> gem install rails

GEM Install

Note − The above command may take some time to install all dependencies. Make sure you are connected to the internet while installing gems dependencies.

Step 4: Check Rails Version

Use the following command to check the rails version.

C:> rails -v

Output

Rails 4.2.4

Congratulations! You are now on Rails over Windows.

Rails Installation on Linux

We are installing Ruby On Rails on Linux using rbenv. It is a lightweight Ruby Version Management Tool. The rbenv provides an easy installation procedure to manage various versions of Ruby, and a solid environment for developing Ruby on Rails applications.

Follow the steps given below to install Ruby on Rails using rbenv tool.

Step 1: Install Prerequisite Dependencies

First of all, we have to install git - core and some ruby dependences that help to install Ruby on Rails. Use the following command for installing Rails dependencies using yum.

tp> sudo yum install -y git-core zlib zlib-devel gcc-c++ patch readline readline-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison curl sqlite-devel

Step 2: Install rbenv

Now we will install rbenv and set the appropriate environment variables. Use the following set of commands to get rbenv for git repository.

tp> git clone git://github.com/sstephenson/rbenv.git .rbenv
tp> echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
tp> echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
tp> exec $SHELL

tp> git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
tp> echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' << ~/.bash_profile
tp> exec $SHELL

Step 3: Install Ruby

Before installing Ruby, determine which version of Ruby you want to install. We will install Ruby 2.2.3. Use the following command for installing Ruby.

tp> rbenv install -v 2.2.3

Use the following command for setting up the current Ruby version as default.

tp> rbenv global 2.2.3

Use the following command to verify the Ruby version.

tp> ruby -v

Output

ruby 2.2.3p173 (2015-08-18 revivion 51636) [X86_64-linux]

Ruby provides a keyword gem for installing the supported dependencies; we call them gems. If you don't want to install the documentation for Ruby-gems, then use the following command.

tp> echo "gem: --no-document" > ~/.gemrc

Thereafter, it is better to install the Bundler gem, because it helps to manage your application dependencies. Use the following command to install bundler gem.

tp> gem install bundler

Step 4: Install Rails

Use the following command for installing Rails version 4.2.4.

tp> install rails -v 4.2.4

Use the following command to make Rails executable available.

tp> rbenv rehash

Use the following command for checking the rails version.

tp> rails -v

Output

tp> Rails 4.2.4

Ruby on Rails framework requires JavaScript Runtime Environment (Node.js) to manage the features of Rails. Next, we will see how we can use Node.js to manage Asset Pipeline which is a Rails feature.

Step 5: Install JavaScript Runtime

Let us install Node.js from the Yum repository. We will take Node.js from EPEL yum repository. Use the following command to add the EPEL package to the yum repository.

tp> sudo yum -y install epel-release

Use the following command for installing the Node.js package.

tp> sudo yum install nodejs

Congratulations! You are now on Rails over Linux.

Step 6: Install Database

By default, Rails uses sqlite3, but you may want to install MySQL, PostgreSQL, or other RDBMS. This is optional; if you have the database installed, then you may skip this step and it is not mandatory that you have a database installed to start the rails server. For this tutorial, we are using PostgreSQL database. Therefore use the following commands to install PostgreSQL.

tp> sudo yum install postgresql-server postgresql-contrib

Accept the prompt, by responding with a y. Use the following command to create a PostgreSQl database cluster.

tp> sudo postgresql-setup initdb

Use the following command to start and enable PostgreSQL.

tp> sudo systemctl start postgresql
tp> sudo systemctl enable postgresql

Keeping Rails Up-to-Date

Assuming you have installed Rails using RubyGems, keeping it up-to-date is relatively easy. We can use the same command in both Windows and Linux platform. Use the following command −

tp> gem update rails

Output

The following screenshot shows a Windows command prompt. The Linux terminal also provides the same output.

GEM Update

This will automatically update your Rails installation. The next time you restart your application, it will pick up this latest version of Rails. While using this command, make sure you are connected to the internet.

Installation Verification

You can verify if everything is set up according to your requirements or not. Use the following command to create a demo project.

tp> rails new demo

Output

Rails New Demo

It will generate a demo rail project; we will discuss about it later. Currently we have to check if the environment is set up or not. Next, use the following command to run WEBrick web server on your machine.

tp> cd demo
tp> rails server

It will generate auto-code to start the server

Rails Server

Now open your browser and type the following −

http://localhost:3000

It should display a message, something like, "Welcome aboard" or "Congratulations".

Rails Welcome

Ruby on Rails - Framework

A framework is a program, set of programs, and/or code library that writes most of your application for you. When you use a framework, your job is to write the parts of the application that make it do the specific things you want.

When you set out to write a Rails application, leaving aside the configuration and other housekeeping chores, you have to perform three primary tasks −

  • Describe and model your application's domain − The domain is the universe of your application. The domain may be a music store, a university, a dating service, an address book, or a hardware inventory. So here you have to figure out what's in it, what entities exist in this universe and how the items in it relate to each other. This is equivalent to modeling a database structure to keep the entities and their relationship.

  • Specify what can happen in this domain − The domain model is static; you have to make it dynamic. Addresses can be added to an address book. Musical scores can be purchased from music stores. Users can log in to a dating service. Students can register for classes at a university. You need to identify all the possible scenarios or actions that the elements of your domain can participate in.

  • Choose and design the publicly available views of the domain − At this point, you can start thinking in Web-browser terms. Once you've decided that your domain has students, and that they can register for classes, you can envision a welcome page, a registration page, and a confirmation page, etc. Each of these pages, or views, shows the user how things stand at a certain point.

Based on the above three tasks, Ruby on Rails deals with a Model/View/Controller (MVC) framework.

Ruby on Rails MVC Framework

The Model View Controller principle divides the work of an application into three separate but closely cooperative subsystems.

Model (ActiveRecord )

It maintains the relationship between the objects and the database and handles validation, association, transactions, and more.

This subsystem is implemented in ActiveRecord library, which provides an interface and binding between the tables in a relational database and the Ruby program code that manipulates database records. Ruby method names are automatically generated from the field names of database tables.

View ( ActionView )

It is a presentation of data in a particular format, triggered by a controller's decision to present the data. They are script-based template systems like JSP, ASP, PHP, and very easy to integrate with AJAX technology.

This subsystem is implemented in ActionView library, which is an Embedded Ruby (ERb) based system for defining presentation templates for data presentation. Every Web connection to a Rails application results in the displaying of a view.

Controller ( ActionController )

The facility within the application that directs traffic, on the one hand, querying the models for specific data, and on the other hand, organizing that data (searching, sorting, messaging it) into a form that fits the needs of a given view.

This subsystem is implemented in ActionController, which is a data broker sitting between ActiveRecord (the database interface) and ActionView (the presentation engine).

Pictorial Representation of MVC Framework

Given below is a pictorial representation of Ruby on Rails Framework −

Rails Framework

Directory Representation of MVC Framework

Assuming a standard, default installation over Linux, you can find them like this −

tp> cd /usr/local/lib/ruby/gems/2.2.0/gems
tp> ls

You will see subdirectories including (but not limited to) the following −

  • actionpack-x.y.z
  • activerecord-x.y.z
  • rails-x.y.z

Over a windows installation, you can find them like this −

tp>cd rubylib
ubygems.2.0gems
rubylib
ubygems.2.0gems>dir

You will see subdirectories including (but not limited to) the following −

MVC

ActionView and ActionController are bundled together under ActionPack.

ActiveRecord provides a range of programming techniques and shortcuts for manipulating data from an SQL database. ActionController and ActionView provides facilities for manipulating and displaying that data. Rails ties it all together.

Ruby on Rails - Directory Structure

When you use the Rails helper script to create your application, it creates the entire directory structure for the application. Rails knows where to find things it needs within this structure, so you don't have to provide any input.

Here is a top-level view of a directory tree created by the helper script at the time of application creation. Except for minor changes between releases, every Rails project will have the same structure, with the same naming conventions. This consistency gives you a tremendous advantage; you can quickly move between Rails projects without relearning the project's organization.

To understand this directory structure, let's use the demo application created in the Installation chapter. It can be created using a simple helper command rails demo.

Now, go into the demo application root directory as follows −

tp> cd demo
demo> dir

You will find a directory structure in Windows as follows −

Directory

Now let's explain the purpose of each directory

  • app − It organizes your application components. It's got subdirectories that hold the view (views and helpers), controller (controllers), and the backend business logic (models).

  • app/controllers − The controllers subdirectory is where Rails looks to find the controller classes. A controller handles a web request from the user.

  • app/helpers − The helpers subdirectory holds any helper classes used to assist the model, view, and controller classes. This helps to keep the model, view, and controller code small, focused, and uncluttered.

  • app/models − The models subdirectory holds the classes that model and wrap the data stored in our application's database. In most frameworks, this part of the application can grow pretty messy, tedious, verbose, and error-prone. Rails makes it dead simple!

  • app/view − The views subdirectory holds the display templates to fill in with data from our application, convert to HTML, and return to the user's browser.

  • app/view/layouts − Holds the template files for layouts to be used with views. This models the common header/footer method of wrapping views. In your views, define a layout using the <tt>layout:default</tt> and create a file named default.html.erb. Inside default.html.erb, call <% yield %> to render the view using this layout.

  • components − This directory holds components, tiny self-contained applications that bundle model, view, and controller.

  • config − This directory contains the small amount of configuration code that your application will need, including your database configuration (in database.yml), your Rails environment structure (environment.rb), and routing of incoming web requests (routes.rb). You can also tailor the behavior of the three Rails environments for test, development, and deployment with files found in the environments directory.

  • db − Usually, your Rails application will have model objects that access relational database tables. You can manage the relational database with scripts you create and place in this directory.

  • doc − Ruby has a framework, called RubyDoc, that can automatically generate documentation for code you create. You can assist RubyDoc with comments in your code. This directory holds all the RubyDoc-generated Rails and application documentation.

  • lib − You'll put libraries here, unless they explicitly belong elsewhere (such as vendor libraries).

  • log − Error logs go here. Rails creates scripts that help you manage various error logs. You'll find separate logs for the server (server.log) and each Rails environment (development.log, test.log, and production.log).

  • public − Like the public directory for a web server, this directory has web files that don't change, such as JavaScript files (public/javascripts), graphics (public/images), stylesheets (public/stylesheets), and HTML files (public).

  • script − This directory holds scripts to launch and manage the various tools that you'll use with Rails. For example, there are scripts to generate code (generate) and launch the web server (server).

  • test − The tests you write and those that Rails creates for you, all goes here. You'll see a subdirectory for mocks (mocks), unit tests (unit), fixtures (fixtures), and functional tests (functional).

  • tmp − Rails uses this directory to hold temporary files for intermediate processing.

  • vendor − Libraries provided by third-party vendors (such as security libraries or database utilities beyond the basic Rails distribution) go here.

Apart from these directories, there will be two files available in demo directory.

  • README − This file contains a basic detail about Rail Application and description of the directory structure explained above.

  • Rakefile − This file is similar to Unix Makefile, which helps with building, packaging and testing the Rails code. This will be used by rake utility supplied along with the Ruby installation.

Ruby on Rails - Examples

In this chapter, we will create a simple but operational online library system for holding and managing the books.

This application has a basic architecture and will be built using two ActiveRecord models to describe the types of data that is stored −

  • Books, which describes an actual listing.
  • Subject, which is used to group books together.

Workflow for Creating Rails Applications

A recommended work flow for creating Rails Application is as follows −

  • Use the rails command to create the basic skeleton of the application.

  • Create a database on the PostgreSQL server to hold your data.

  • Configure the application to know where your database is located and the login credentials for it.

  • Create Rails Active Records (Models), because they are the business objects you'll be working with in your controllers.

  • Generate Migrations that simplify the creating and maintaining of database tables and columns.

  • Write Controller Code to put a life in your application.

  • Create Views to present your data through User Interface.

So, let us start with creating our library application.

Creating an Empty Rails Web Application

Rails is both a runtime web application framework and a set of helper scripts that automate many of the things you do when developing a web application. In this step, we will use one such helper script to create the entire directory structure and the initial set of files to start our Library System application.

  • Go into ruby installation directory to create your application.

  • Run the following command to create a skeleton for library application. It will create the directory structure in the current directory.

tp> rails new library

This will create a subdirectory for the library application containing a complete directory tree of folders and files for an empty Rails application. Check a complete directory structure of the application. Check Rails Directory Structure for more detail.

Most of our development work will be creating and editing files in the library/app subdirectories. Here's a quick run down of how to use them −

  • The controllers subdirectory is where Rails looks to find controller classes. A controller handles a web request from the user.

  • The views subdirectory holds the display templates to fill in with data from our application, convert to HTML, and return to the user's browser.

  • The models subdirectory holds the classes that model and wrap the data stored in our application's database. In most frameworks, this part of the application can grow pretty messy, tedious, verbose, and error-prone. Rails makes it dead simple.

  • The helpers subdirectory holds any helper classes used to assist the model, view, and controller classes. This helps to keep the model, view, and controller code small, focused, and uncluttered.

Starting Web Server

Rails web application can run under virtually any web server, but the most convenient way to develop a Rails web application is to use the built-in WEBrick web server. Let's start this web server and then browse to our empty library application −

This server will be started from the application directory as follows. It runs on port number 3000.

tp> cd rubylibrary 
tp
ubylibrary> Rails server

It generates the auto code to start the server as shown below −

Rails Server

This will start your WEBrick web server.

Now open your browser and browse to http://127.0.0.1:3000. If everything is gone fine, then you should see a greeting message from WEBrick, otherwise there is something wrong with your setting. If everything goes well it will generate the output as follows.

Web Server

What is next?

The next chapter explains how to create databases for your application and what is the configuration required to access these created databases.

Further, we will see what Rails Migration is and how it is used to maintain database tables.

Ruby on Rails - Database Setup

Before starting with this chapter, make sure your database server is up and running. Ruby on Rails recommends to create three databases - a database each for development, testing, and production environment. According to convention, their names should be −

  • library_development
  • library_production
  • library_test

You should initialize all three of them and create a user and password for them with full read and write privileges. We are using the root user ID for our application.

Database Setup for MySQL

In MySQL, we are using the root user ID for our application. The MySQL console session in which you do this looks something like −

mysql> create database library_development;
Query OK, 1 row affected (0.01 sec)

mysql> grant all privileges on library_development.*
to 'root'@'localhost' identified by 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

You can do the same thing for two more databases library_production and library_test.

Configuring database.yml

At this point, you need to let Rails know about the user name and password for the databases. You do this in the file database.yml, available in the libraryconfig subdirectory of Rails Application you created. This file has live configuration sections for MySQL databases. In each of the sections you use, you need to change the username and password lines to reflect the permissions on the databases you've created.

When you finish, it should look something like −

development:
   adapter: mysql
   database: library_development
   username: root
   password: [password]
   host: localhost
	
test:
   adapter: mysql
   database: library_test
   username: root
   password: [password]
   host: localhost
   
production:
   adapter: mysql
   database: library_production
   username: root
   password: [password]
   host: localhost

Database Setup for PostgreSQL

By default, PostgreSQL does not provide any users. We have to create new users. Use the following command to create a user with the name rubyuser.

tp> sudo -u postgres createuser rubyuser -s

If you want to create a password for the new user, then use the following command.

tp> sudo -u postgres psql

postgres=# password rubyuser

Use the following command for creating a database library_development.

postgres=# CREATE DATABASE library_development OWNER rubyuser; 

CREATE DATABASE

Use the following command for creating a database library_production.

postgres=# CREATE DATABASE library_production OWNER rubyuser; 

CREATE DATABASE

Use the following command for creating a database library_test.

postgres=# CREATE DATABASE library_test OWNER rubyuser; 

CREATE DATABASE

Press Ctrl+D to terminate PosgreSQL.

Configuring database.yml

At this point, you need to let Rails know the username and password for the databases. You do this in the file database.yml, available in the libraryconfig subdirectory of Rails Application you created. This file has live configuration sections for PostgreSQL databases. In each of the sections, you need to change the username and password lines to reflect the permissions on the databases you've created.

When you finish, it should look as follows −

default: &default
   adapter: postgresql
   encoding: unicode
  
development:
   adapter: postgresql
   encoding: unicode
   database: library_development
   username: rubyuser
   password: <Password for rubyuser>

test:
   adapter: postgresql
   encoding: unicode
   database: library_test
   username: rubyuser
   password: <Password for rubyuser>
 
production:
   adapter: postgresql
   encoding: unicode
   database: library_production
   username: rubyuser
   password: <Password for rubyuser>

What is Next?

The next two chapters explain how to model your database tables and how to manage those using Rails Migrations.

Ruby on Rails - Active Records

Rails Active Record is the Object/Relational Mapping (ORM) layer supplied with Rails. It closely follows the standard ORM model, which is as follows −

  • tables map to classes,
  • rows map to objects and
  • columns map to object attributes.

Rails Active Records provide an interface and binding between the tables in a relational database and the Ruby program code that manipulates database records. Ruby method names are automatically generated from the field names of database tables.

Each Active Record object has CRUD (Create, Read, Update, and Delete) methods for database access. This strategy allows simple designs and straight forward mappings between database tables and application objects.

Translating a Domain Model into SQL

Translating a domain model into SQL is generally straight forward, as long as you remember that you have to write Rails-friendly SQL. In practical terms, you have to follow certain rules −

  • Each entity (such as book) gets a table in the database named after it, but in the plural (books).

  • Each such entity-matching table has a field called id, which contains a unique integer for each record inserted into the table.

  • Given entity x and entity y, if entity y belongs to entity x, then table y has a field called x_id.

  • The bulk of the fields in any table store the values for that entity's simple properties (anything that's a number or a string).

Creating Active Record Files (Models)

To create the Active Record files for our entities for library application, introduced in the previous chapter, issue the following command from the top level of the application directory.

library> ruby script/generate model Book
library> ruby script/generate model Subject

Above rails generate model book commands generates the auto code as below −

Book Generate

You're telling the generator to create models called Book and Subject to store instances of books and subjects. Notice that you are capitalizing Book and Subject and using the singular form. This is a Rails paradigm that you should follow each time you create a model.

When you use the generate tool, Rails creates the actual model file that holds all the methods unique to the model and the business rules you define, a unit test file for performing test-driven development, a sample data file (called fixtures) to use with the unit tests, and a Rails migration that makes creating database tables and columns easy.

Apart from creating many other files and directories, this will create files named book.rb and subject.rb containing a skeleton definition in the app/models directory.

Content available in book.rb −

class Book < ActiveRecord::Base
end

Content available in subject.rb −

class Subject < ActiveRecord::Base
end

Creating Associations between Models

When you have more than one model in your rails application, you would need to create connection between those models. You can do this via associations. Active Record supports three types of associations −

  • one-to-one − A one-to-one relationship exists when one item has exactly one of another item. For example, a person has exactly one birthday or a dog has exactly one owner.

  • one-to-many − A one-to-many relationship exists when a single object can be a member of many other objects. For instance, one subject can have many books.

  • many-to-many − A many-to-many relationship exists when the first object is related to one or more of a second object, and the second object is related to one or many of the first object.

You indicate these associations by adding declarations to your models: has_one, has_many, belongs_to, and has_and_belongs_to_many.

Now, you need to tell Rails what relationships you want to establish within the library data system. To do so, modify book.rb and subject.rb to look like this −

class Book < ActiveRecord::Base
   belongs_to :subject
end

We have used a singular subject in the above example, because one Book can belong to a single Subject.

class Subject < ActiveRecord::Base
   has_many :books
end

We have used plural books here, because one subject can have multiple books.

Implementing Validations on Models

The implementation of validations is done in a Rails model. The data you are entering into the database is defined in the actual Rails model, so it only makes sense to define what valid data entails in the same location.

The validations are −

  • The value of title field should not be NULL.

  • The value of price field should be numeric.

Open book.rb in the appmodel subdiractory and put the following validations −

class Book < ActiveRecord::Base
   belongs_to :subject
   validates_presence_of :title
   validates_numericality_of :price, :message=>"Error Message"
end
  • validates_presence_of − protects "NOT NULL" fields against missing user input.

  • validates_numericality_of − prevents the user, entering non numeric data.

Besides the validations mentioned above, there are other common validations. Check Rails Quick Guide.

What is Next?

In the next chapter, we will learn Rails Migration, which allows you to use Ruby to define changes to your database schema, making it possible to use a version control system to keep things synchronized with the actual code.

Ruby on Rails - Migrations

Rails Migration allows you to use Ruby to define changes to your database schema, making it possible to use a version control system to keep things synchronized with the actual code.

This has many uses, including −

  • Teams of developers − If one person makes a schema change, the other developers just need to update, and run "rake migrate".

  • Production servers − Run "rake migrate" when you roll out a new release to bring the database up to date as well.

  • Multiple machines − If you develop on both a desktop and a laptop, or in more than one location, migrations can help you keep them all synchronized.

What Can Rails Migration Do?

  • create_table(name, options)
  • drop_table(name)
  • rename_table(old_name, new_name)
  • add_column(table_name, column_name, type, options)
  • rename_column(table_name, column_name, new_column_name)
  • change_column(table_name, column_name, type, options)
  • remove_column(table_name, column_name)
  • add_index(table_name, column_name, index_type)
  • remove_index(table_name, column_name)

Migrations support all the basic data types − The following is the list of data types that migration supports −

  • string − for small data types such as a title.

  • text − for longer pieces of textual data, such as the description.

  • integer − for whole numbers.

  • float − for decimals.

  • datetime and timestamp − store the date and time into a column.

  • date and time − store either the date only or time only.

  • binary − for storing data such as images, audio, or movies.

  • Boolean − for storing true or false values.

Valid column options are − The following is the list of valid column options.

  • limit ( :limit => “50” )

  • default (:default => “blah” )

  • null (:null => false implies NOT NULL)

NOTE − The activities done by Rails Migration can be done using any front-end GUI or directly on SQL prompt, but Rails Migration makes all those activities very easy.

See the Rails API for details on these.

Create the Migrations

Here is the generic syntax for creating a migration −

application_dir> rails generate migration table_name

This will create the file db/migrate/001_table_name.rb. A migration file contains the basic Ruby syntax that describes the data structure of a database table.

NOTE − Before running the migration generator, it is recommended to clean the existing migrations generated by model generators.

We will create two migrations corresponding to our three tables − books and subjects.

Books migration should be as follows −

tp> cd library
library> rails generate migration books

Above command generates the following code.

Genarate

subject migration should be as follows −

tp> cd library
library> rails generate migration subjects

Above command generates the following code.

Genarate

Notice that you are using lower case for book and subject and plural form while creating migrations. This is a Rails paradigm that you should follow each time you create a Migration.

Edit the Code

Go to db/migrate subdirectory of your application and edit each file one by one using any simple text editor.

Modify 001_books.rb as follows −

The ID column will be created automatically, so don't do it here as well.

class Books < ActiveRecord::Migration
   
   def self.up
      create_table :books do |t|
         t.column :title, :string, :limit => 32, :null => false
         t.column :price, :float
         t.column :subject_id, :integer
         t.column :description, :text
         t.column :created_at, :timestamp
      end
   end

   def self.down
      drop_table :books
   end
end

The method self.up is used when migrating to a new version, self.down is used to roll back any changes if needed. At this moment, the above script will be used to create books table.

Modify 002_subjects.rb as follows −

class Subjects < ActiveRecord::Migration
   def self.up
      
      create_table :subjects do |t|
         t.column :name, :string
      end
	
      Subject.create :name => "Physics"
      Subject.create :name => "Mathematics"
      Subject.create :name => "Chemistry"
      Subject.create :name => "Psychology"
      Subject.create :name => "Geography"
   end

   def self.down
      drop_table :subjects
   end
end

The above script will be used to create subjects table and will create five records in the subjects table.

Run the Migration

Now that you have created all the required migration files. It is time to execute them against the database. To do this, go to a command prompt and go to the library directory in which the application is located, and then type rake migrate as follows −

library> rake db:migrate

This will create a "schema_info" table if it doesn't exist, which tracks the current version of the database - each new migration will be a new version, and any new migrations will be run until your database is at the current version.

Rake is a Ruby build program similar to Unix make program that Rails takes advantage of, to simplify the execution of complex tasks such as updating a database's structure etc.

Running Migrations for Production and Test Databases

If you would like to specify what Rails environment to use for the migration, use the RAILS_ENV shell variable.

For example −

library> export RAILS_ENV = production
library> rake db:migrate
library> export RAILS_ENV = test
library> rake db:migrate
library> export RAILS_ENV = development
library> rake db:migrate

NOTE − In Windows, use "set RAILS_ENV = production" instead of export command.

What is Next?

Now we have our database and the required tables available. In the two subsequent chapters, we will explore two important components called Controller (ActionController) and View (ActionView).

  • Creating Controllers (Action Controller).

  • Creating Views (Action View).

Ruby on Rails - Controller

The Rails controller is the logical center of your application. It coordinates the interaction between the user, the views, and the model. The controller is also a home to a number of important ancillary services.

  • It is responsible for routing external requests to internal actions. It handles people-friendly URLs extremely well.

  • It manages caching, which can give applications orders-of-magnitude performance boosts.

  • It manages helper modules, which extend the capabilities of the view templates without bulking up their code.

  • It manages sessions, giving users the impression of an ongoing interaction with our applications.

The process for creating a controller is very easy, and it's similar to the process we've already used for creating a model. We will create just one controller here −

library> rails generate controller Book

Notice that you are capitalizing Book and using the singular form. This is a Rails paradigm that you should follow each time you create a controller.

This command accomplishes several tasks, of which the following are relevant here −

  • It creates a file called app/controllers/book_controller.rb

If you look at book_controller.rb, you will find it as follows −

class BookController < ApplicationController
end

Controller classes inherit from ApplicationController, which is the other file in the controllers folder: application.rb.

The ApplicationController contains code that can be run in all your controllers and it inherits from Rails ActionController::Base class.

You don't need to worry with the ApplicationController as of yet, so let's just define a few method stubs in book_controller.rb. Based on your requirement, you could define any number of functions in this file.

Modify the file to look like the following and save your changes. Note that it is upto you what name you want to give to these methods, but better to give relevant names.

class BookController < ApplicationController
   def list
   end
   
   def show
   end
   
   def new
   end
   
   def create
   end
   
   def edit
   end
   
   def update
   end
   
   def delete
   end
   
end

Now let us implement all the methods one by one.

Implementing the list Method

The list method gives you a list of all the books in the database. This functionality will be achieved by the following lines of code. Edit the following lines in book_controller.rb file.

def list
   @books = Book.all
end

The @books = Book.all line in the list method tells Rails to search the books table and store each row it finds in the @books instance object.

Implementing the show Method

The show method displays only further details on a single book. This functionality will be achieved by the following lines of code.

def show
   @book = Book.find(params[:id])
end

The show method's @book = Book.find(params[:id]) line tells Rails to find only the book that has the id defined in params[:id].

The params object is a container that enables you to pass values between method calls. For example, when you're on the page called by the list method, you can click a link for a specific book, and it passes the id of that book via the params object so that show can find the specific book.

Implementing the new Method

The new method lets Rails know that you will create a new object. So just add the following code in this method.

def new
   @book = Book.new
   @subjects = Subject.all
end

The above method will be called when you will display a page to the user to take user input. Here second line grabs all the subjects from the database and puts them in an array called @subjects.

Implementing the create Method

Once you take user input using HTML form, it is time to create a record into the database. To achieve this, edit the create method in the book_controller.rb to match the following −

def create
   @book = Book.new(book_params)
	
   if @book.save
      redirect_to :action => 'list'
   else
      @subjects = Subject.all
      render :action => 'new'
   end
   
end

def book_params
   params.require(:books).permit(:title, :price, :subject_id, :description)
end

The first line creates a new instance variable called @book that holds a Book object built from the data, the user submitted. The book_params method is used to collect all the fields from object :books. The data was passed from the new method to create using the params object.

The next line is a conditional statement that redirects the user to the list method if the object saves correctly to the database. If it doesn't save, the user is sent back to the new method. The redirect_to method is similar to performing a meta refresh on a web page: it automatically forwards you to your destination without any user interaction.

Then @subjects = Subject.all is required in case it does not save data successfully and it becomes similar case as with new option.

Implementing the edit Method

The edit method looks nearly identical to the show method. Both methods are used to retrieve a single object based on its id and display it on a page. The only difference is that the show method is not editable.

def edit
   @book = Book.find(params[:id])
   @subjects = Subject.all
end

This method will be called to display data on the screen to be modified by the user. The second line grabs all the subjects from the database and puts them in an array called @subjects.

Implementing the update Method

This method will be called after the edit method, when the user modifies a data and wants to update the changes into the database. The update method is similar to the create method and will be used to update existing books in the database.

def update
   @book = Book.find(params[:id])
	
   if @book.update_attributes(book_param)
      redirect_to :action => 'show', :id => @book
   else
      @subjects = Subject.all
      render :action => 'edit'
   end
   
end

def book_param
   params.require(:book).permit(:title, :price, :subject_id, :description)
end

The update_attributes method is similar to the save method used by create but instead of creating a new row in the database, it overwrites the attributes of the existing row.

Then @subjects = Subject.all line is required in case it does not save the data successfully, then it becomes similar to edit option.

Implementing the delete Method

If you want to delete a record from the database then you will use this method. Implement this method as follows.

def delete
   Book.find(params[:id]).destroy
   redirect_to :action => 'list'
end

The first line finds the classified based on the parameter passed via the params object and then deletes it using the destroy method. The second line redirects the user to the list method using a redirect_to call.

Additional Methods to Display Subjects

Assume you want to give a facility to your users to browse all the books based on a given subject. So, you can create a method inside book_controller.rb to display all the subjects. Assume the method name is show_subjects

def show_subjects
   @subject = Subject.find(params[:id])
end

Finally your book_controller.rb file will look as follows −

class BooksController < ApplicationController

   def list
      @books = Book.all
   end

   def show
      @book = Book.find(params[:id])
   end
  
   def new
      @book = Book.new
      @subjects = Subject.all
   end

   def book_params
      params.require(:books).permit(:title, :price, :subject_id, :description)
   end

   def create
      @book = Book.new(book_params)

      if @book.save
         redirect_to :action => 'list'
      else
         @subjects = Subject.all
         render :action => 'new'
      end
   end
   
   def edit
      @book = Book.find(params[:id])
      @subjects = Subject.all
   end
   
   def book_param
      params.require(:book).permit(:title, :price, :subject_id, :description)
   end
   
   def update
      @book = Book.find(params[:id])
      
      if @book.update_attributes(book_param)
         redirect_to :action => 'show', :id => @book
      else
         @subjects = Subject.all
         render :action => 'edit'
      end
   end
   
   def delete
      Book.find(params[:id]).destroy
      redirect_to :action => 'list'
   end
   
   def show_subjects
      @subject = Subject.find(params[:id])
   end

end

Now save your controller file.

What is Next?

You have created almost all the methods, which will work on backend. Next we will define routes (URLs) for actions.

Ruby on Rails - Routes

The routing module provides URL rewriting in native Ruby. It's a way to redirect incoming requests to controllers and actions. It replaces the mod_rewrite rules. Best of all, Rails' Routing works with any web server. Routes are defined in app/config/routes.rb.

Think of creating routes as drawing a map for your requests. The map tells them where to go based on some predefined pattern −

Rails.application.routes.draw do
   Pattern 1 tells some request to go to one place
   Pattern 2 tell them to go to another
   ...
end

Example

Let us consider our library management application contains a controller called BookController. We have to define the routes for those actions which are defined as methods in the BookController class.

Open routes.rb file in library/config/ directory and edit it with the following content.

Rails.application.routes.draw do
   get 'book/list'
   get 'book/new'
   post 'book/create'
   patch 'book/update'
   get 'book/list'
   get 'book/show'
   get 'book/edit'
   get 'book/delete'
   get 'book/update'
   get 'book/show_subjects'
end

The routes.rb file defines the actions available in the applications and the type of action such as get, post, and patch.

Use the following command to list all your defined routes, which are useful for tracking down routing problems in your application, or giving you a good overview of the URLs in an application you're trying to get familiar with.

library> rake routes

What is Next?

Next, we will create the code to generate screens to display data and to take input from the user.

Ruby on Rails - Views

A Rails View is an ERb program that shares data with controllers through mutually accessible variables.

If you look in the app/views directory of the library application, you will see one subdirectory for each of the controllers, we have created: book. Each of these subdirectories was created automatically when the same-named controller was created with the generate script.

Rails let's you know that you need to create the view file for each new method. Each method you define in the controller needs to have a corresponding erb file, with the same name as the method, to display the data that the method is collecting.

So let's create view files for all the methods we have defined in the book_controller.rb. While executing these views, simultaneously check these actions are applicable into the database or not.

Creating View File for list Method

Create a file called list.html.erb using your favourite text editor and save it to app/views/book. After creating and saving the file, refresh your web browser. You should see a blank page; if you don't, check the spelling of your file and make sure that it is exactly the same as your controller's method.

Now, display the actual content. Let us put the following code into list.html.erb.

<% if @books.blank? %>
<p>There are not any books currently in the system.</p>
<% else %>
<p>These are the current books in our system</p>

<ul id = "books">
   <% @books.each do |c| %>
   <li><%= link_to c.title, {:action => 'show', :id => c.id} -%></li>
   <% end %>
</ul>

<% end %>
<p><%= link_to "Add new Book", {:action => 'new' }%></p>

The code to be executed is to check whether the @books array has any objects in it. The .blank? method returns true if the array is empty, and false if it contains any objects. This @books object was created in controller inside the list method.

The code between the <%= %> tags is a link_to method call. The first parameter of link_to is the text to be displayed between the <a> tags. The second parameter is what action is called when the link is clicked. In this case, it is the show method. The final parameter is the id of the book that is passed via the params object.

Now, try refreshing your browser and you should get the following screen because we don't have any book in our library.

No Book Message

Creating View File for new Method

Till now, we don't have any book in our library. We have to create few books in the system. So, let us design a view corresponding to the new method defined in the book_controller.rb.

Create a file called new.html.erb using your favorite text editor and save it to app/views/book. Add the following code to the new.html.erb file.

<h1>Add new book</h1>

<%= form_tag :action => 'create' do %>
<p><label for = "book_title">Title</label>:

<%= text_field 'books', 'title' %></p>
<p><label for = "book_price">Price</label>:

<%= text_field 'books', 'price' %></p>
<p><label for = "book_subject_id">Subject</label>:

<%= collection_select(:books, :subject_id, @subjects, :id, :name, prompt: true) %></p>
<p><label for = "book_description">Description</label><br/>

<%= text_area 'books', 'description' %></p>
<%= submit_tag "Create" %>

<% end -%>
<%= link_to 'Back', {:action => 'list'} %>

Here form_tag method interprets the Ruby code into a regular HTML <form> tag using all the information supplied to it. This tag, for example, outputs the following HTML −

<form action = "/book/create" method = "post">

Next method is text_field that outputs an <input> text field. The parameters for text_field are object and field name. In this case, the object is book and the name is title.

Rails method called collection_select, creates an HTML select menu built from an array, such as the @books one. There are five parameters, which are as follows −

  • :book − The object you are manipulating. In this case, it's a book object.

  • :subject_id − The field that is populated when the book is saved.

  • @books − The array you are working with.

  • :id − The value that is stored in the database. In terms of HTML, this is the <option> tag's value parameter.

  • :name − The output that the user sees in the pull-down menu. This is the value between the <option> tags.

The next used is submit_tag, which outputs an <input> button that submits the form. Finally, there is the end method that simply translates into </form>.

Go to your browser and visit http://localhost:3000/book/new. This will give you the following screen.

New Book

Enter some data in this form and then click the Create button. Here i have added the following details into the fields −

Title: Advance Physics
Price: 390
Subject: Physics
Description: This is test to create new book

When you click the Create button, it will call the create method, which does not need any view because this method is using either list or new methods to view the results. So, when you click the Create button, the data should submit successfully and redirect you to the list page, in which you now have a single item listed as follows −

Create Book

If you click the link, you should see another Template is missing error, since you haven't created the template file for show method yet.

Creating View File for show Method

This method will display the complete detail about any book available in the library. Create a show.html.erb file under app/views/book and populate it with the following code −

<h1><%= @book.title %></h1>

<p>
   <strong>Price: </strong> $<%= @book.price %><br />
   <strong>Subject :</strong> <%= @book.subject.name %><br />
   <strong>Created Date:</strong> <%= @book.created_at %><br />
</p>

<p><%= @book.description %></p>

<hr />

<%= link_to 'Back', {:action => 'list'} %>

This is the first time you have taken the full advantage of associations, which enable you to easily pull data from related objects.

The format used is @variable.relatedObject.column. In this instance, you can pull the subject's name value through the @book variable using the belongs_to associations. If click on any listed record then it will show you the following screen.

Show Book

Creating View File for edit Method

Create a new file called edit.html.erb and save it in app/views/book. Populate it with the following code −

<h1>Edit Book Detail</h1>

<%= form_for @book, :url =>{:action => "update", :id =>@book} do |f| %>

<p>Title: <%= f.text_field 'title' %></p>
<p>Price: <%= f.text_field  'price' %></p>
<p>Subject: <%= f.collection_select :subject_id, Subject.all, :id, :name %></p>
<p>Description<br/>

<%= f.text_area 'description' %></p>
<%= f.submit "Save changes" %>
<% end %>

<%= link_to 'Back', {:action => 'list' } %>

This code is very similar to the new method except action to be updated instead of creating and defining an id.

In this scenario, we used form_for tag for the form action. It will perform better than form_tag. Why because it will create interaction with the Model easily. Therefore it is better to use form_for tag whenever you need interaction between the model and the form fields.

At this point, we need some modification in the list method's view file. Go to the <li></li> element and modify it to look like the following −

<li>
   <%= link_to c.title, {:action => "show", :id => c.id} -%>
   <b> <%= link_to 'Edit', {:action => "edit",
   :id => c.id} %></b>
</li>

Now, try to browse books using the http://localhost:3000/book/list. It will give you the listing of all the books along with Edit option. When you click the Edit option, then you will have next screen as follows −

Edit Book

Now, you edit this information and then click the Save Changes button. This will result in a call to update method available in the controller file and it will update all the changed attribute. Notice that the update method does not need any view file because it's using either show or edit methods to show its results.

Creating View File for delete Method

Removing information from a database using Ruby on Rails is almost too easy. You do not need to write any view code for the delete method because this method is using list method to display the result. So, let's just modify list.html.erb again and add a delete link.

Go to the <li></li> element and modify it to look like the following −

<li>
   <%= link_to c.title, {:action => 'show', :id => c.id} -%>
   <b> <%= link_to 'Edit', {:action => 'edit', :id => c.id} %></b>
   <b> <%= link_to "Delete", {:action => 'delete', :id => c.id},
   :confirm => "Are you sure you want to delete this item?" %></b>
</li>

The :confirm parameter presents a JavaScript confirmation box asking if you really want to perform the action. If the user clicks OK, the action proceeds, and the item is deleted.

Now, try browsing books using http://localhost:3000/book/list. It will give you listing of all the books along with Edit and Delete options as follows −

Delete Book

Now using the Delete option, you can delete any listed record.

Creating View File for show_subjects Method

Create a new file, show_subjects.html.erb, in the app/views/book directory and add the following code to it −

<h1><%= @subject.name -%></h1>

<ul>
   <% @subject.books.each do |c| %>
   <li><%= link_to c.title, :action => "show", :id => c.id -%></li>
   <% end %>
</ul>

You are taking advantage of associations by iterating through a single subject's many books listings.

Now modify the Subject: line of show.html.erb so that the subject listing shows a link.

<strong>Subject: </strong> <%= link_to @book.subject.name,
:action => "show_subjects", :id => @book.subject.id %><br />

This will output a list of subject on the index page, so that users can access them directly.

Modify list.html.erb to add the following to the top of the file −

<ul id = "subjects">
   <% Subject.find(:all).each do |c| %>
   <li><%= link_to c.name, :action => "show_subjects", :id => c.id %></li>
   <% end %>
</ul>

Now try browsing books using http://localhost:3000/book/list. It will display all subjects with links so that you can browse all the books related to that subject.

List Subjects

What is Next?

Hope now you are feeling comfortable with all the operations of Rails.

The next chapter explains how to use Layouts to put your data in a better way. We will show you how to use CSS in your Rails applications.

Ruby on Rails - Layouts

A layout defines the surroundings of an HTML page. It's the place to define a common look and feel of your final output. Layout files reside in app/views/layouts.

The process involves defining a layout template and then letting the controller know that it exists and to use it. First, let's create the template.

Add a new file called standard.html.erb to app/views/layouts. You let the controllers know what template to use by the name of the file, so following a same naming scheme is advised.

Add the following code to the new standard.html.erb file and save your changes −

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns = "http://www.w3.org/1999/xhtml">

   <head>
      <meta http-equiv = "Content-Type" content = "text/html; charset = iso-8859-1" />
      <meta http-equiv = "Content-Language" content = "en-us" />
      <title>Library Info System</title>
      <%= stylesheet_link_tag "style" %>
   </head>

   <body id = "library">
      <div id = "container">
         
         <div id = "header">
            <h1>Library Info System</h1>
            <h3>Library powered by Ruby on Rails</h3>
         </div>

         <div id = "content">
            <%= yield -%>
         </div>

         <div id = "sidebar"></div>
         
      </div>
   </body>
   
</html>

Everything you just added were standard HTML elements except two lines. The stylesheet_link_tag helper method outputs a stylesheet <link>. In this instance, we are linking style.css style sheet. The yield command lets Rails know that it should put the html.erb for the method called here.

Now open book_controller.rb and add the following line just below the first line −

class BookController < ApplicationController
layout 'standard'
def list
@books = Book.all
end
...................

It instructs the controller that we want to use a layout available in the standard.html.erb file. Now try browsing books that will produce the following screen.

Layout Example

Adding Style Sheet

Till now, we have not created any style sheet, so Rails is using the default style sheet. Now let's create a new file called style.css and save it in /public/stylesheets. Add the following code to this file.

body {
   font-family: Helvetica, Geneva, Arial, sans-serif;
   font-size: small;
   font-color: #000;
   background-color: #fff;
}

a:link, a:active, a:visited {
   color: #CD0000;
}

input { 
   margin-bottom: 5px;
}

p { 
   line-height: 150%;
}

div#container {
   width: 760px;
   margin: 0 auto;
}

div#header {
   text-align: center;
   padding-bottom: 15px;
}

div#content {
   float: left;
   width: 450px;
   padding: 10px;
}

div#content h3 {
   margin-top: 15px;
}

ul#books {
   list-style-type: none;
}

ul#books li {
   line-height: 140%;
}

div#sidebar {
   width: 200px;
   margin-left: 480px;
}

ul#subjects {
   width: 700px;
   text-align: center;
   padding: 5px;
   background-color: #ececec;
   border: 1px solid #ccc;
   margin-bottom: 20px;
}

ul#subjects li {
   display: inline;
   padding-left: 5px;
}

Now refresh your browser and see the difference −

Layout Example

What is Next?

The next chapter explains how to develop applications using Rails Scaffolding to give user access to add, delete, and modify the records in any database.

Ruby on Rails - Scaffolding

While you're developing Rails applications, especially those which are mainly providing you with a simple interface to data in a database, it can often be useful to use the scaffold method.

Scaffolding provides more than cheap demo thrills. Here are some benefits −

  • You can quickly get code in front of your users for feedback.

  • You are motivated by faster success.

  • You can learn how Rails works by looking at the generated code.

  • You can use scaffolding as a foundation to jump start your development.

Scaffolding Example

To understand scaffolding, let's create a database called cookbook and a table called recipes.

Creating an Empty Rails Web Application

Open a command window and navigate to where you want to create this cookbook web application. So, run the following command to create a complete directory structure.

tp> rails new cookbook

Setting up the Database

Here is the way to create a database −

mysql> create database cookbook;
Query OK, 1 row affected (0.01 sec)

mysql> grant all privileges on cookbook.*
to 'root'@'localhost' identified by 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

To instruct Rails how to find the database, edit the configuration file cookbookconfigdatabase.yml and change the database name to cookbook. Leave the password empty. When you finish, it should look as follows −

development:
   adapter: mysql
   database: cookbook
   username: root
   password: [password]
   host: localhost
	
test:
   adapter: mysql
   database: cookbook
   username: root
   password: [password]
   host: localhost
	
production:
   adapter: mysql
   database: cookbook
   username: root
   password: [password]
   host: localhost

Rails lets you run in the development mode, test mode, or production mode, using different databases. This application uses the same database for each.

The Generated Scaffold Code

With the scaffold action, Rails generates all the code it needs dynamically. By running scaffold as a script, we can get all the code written to disk, where we can investigate it and then start tailoring it to our requirements.

So now, let's start once again to generate Scaffold code manually by using the scaffold helper script −

cookbook> rails generate scaffold recipe

It generates auto-files as shown below −

Scaffold

The Controller

Let's look at the code behind the controller. This code is generated by the scaffold generator. If you open app/controllers/recipes_controller.rb, then you will find something as follows −

class RecipesController < ApplicationController
   before_action :set_recipe, only: [:show, :edit, :update, :destroy]
   
   # GET /recipes
   # GET /recipes.json
   def index
      @recipes = Recipe.all
   end
   
   # GET /recipes/1
   # GET /recipes/1.json
   def show
   end
   
   # GET /recipes/new
   def new
      @recipe = Recipe.new
   end
   
   # GET /recipes/1/edit
   def edit
   end
   
   # POST /recipes
   # POST /recipes.json
   def create
      @recipe = Recipe.new(recipe_params)
      
      respond_to do |format|
         if @recipe.save
            format.html { redirect_to @recipe, notice: 'Recipe was successfully created.' }
            format.json { render :show, status: :created, location: @recipe }
         else
            format.html { render :new }
            format.json { render json: @recipe.errors, status: :unprocessable_entity }
         end
      end
      
   end
   
   # PATCH/PUT /recipes/1
   # PATCH/PUT /recipes/1.json
   def update
      respond_to do |format|
         if @recipe.update(recipe_params)
            format.html { redirect_to @recipe, notice: 'Recipe was successfully updated.' }
            format.json { render :show, status: :ok, location: @recipe }
         else
            format.html { render :edit }
            format.json { render json: @recipe.errors, status: :unprocessable_entity }
         end
      end
      
   end
   
   # DELETE /recipes/1
   # DELETE /recipes/1.json
   def destroy
      @recipe.destroy
         respond_to do |format|
         format.html { redirect_to recipes_url, notice: 'Recipe was successfully destroyed.' }
         format.json { head :no_content }
      end
   end
   
   private
   
   # Use callbacks to share common setup or constraints between actions.
   def set_recipe
      @recipe = Recipe.find(params[:id])
   end
   
   # Never trust parameters from the scary internet, only allow the white list through.
   def recipe_params
      params.require(:recipe).permit(:tittle, :instructions)
   end
end

When the user of a Rails application selects an action, e.g. "Show" - the controller will execute any code in the appropriate section - "def show" - and then by default will render a template of the same name - "show.html.erb". This default behavior can be overwritten.

The controller uses ActiveRecord methods such as find, find_all, new, save, update_attributes, and destroy to move data to and from the database tables. Note that you do not have to write any SQL statements, rails will take care of it automatically.

This single line of code will bring the database table to life. It will provide with a simple interface to your data, and ways of −

  • Creating new entries
  • Editing current entries
  • Viewing current entries
  • Destroying current entries

When creating or editing an entry, scaffold will do all the hard work like form generation and handling for you, and will even provide clever form generation, supporting the following types of inputs −

  • Simple text strings
  • Text areas (or large blocks of text)
  • Date selectors
  • Date-time selectors

You can use Rails Migrations to create and maintain tables.

rake db:migrate RAILS_ENV=development

Now, go to the cookbook directory and run the Web Server using the following command −

cookbook> rails server

Now, open a browser and navigate to http://127.0.0.1:3000/recipe/new. This will provide you a screen to create new entries in the recipes table. A screenshot is shown below −

Create Recipe

Once you press the Create button to create a new recipe, your record is added into the recipes table and it shows the following result −

Create Recipe

You can see the option to edit, show, and destroy the records. So, play around with these options.

You can also list down all the recipes available in the recipes table using the URL http://127.0.0.1:3000/recipe/list.

Enhancing the Model

Rails gives you a lot of error handling for free. To understand this, add some validation rules to the empty recipe model −

Modify app/models/recipe.rb as follows and then test your application −

class Recipe < ActiveRecord::Base
   validates_length_of :title, :within => 1..20
   validates_uniqueness_of :title, :message => "already exists"
end

These entries will give automatic checking.

  • validates_length_of − the field is not blank and not too long.

  • validates_uniqueness_of − duplicate values are trapped. Instead of the default Rails error message, we have given a custom message here.

Alternative Way to Create Scaffolding

Create an application as shown above and The Generated Scaffold Code as shown below

rails g scaffold Recipe tittle:string instructions:text

Above code generates the auto files with data base by using with sqlite3 with tittle and instruction column as shown below an image.

Scaffold

we need to migrate the data base by using below syntax.

$ rake db:migrate RAILS_ENV=development

Finally run the application by using the following command line −

rails server

It will generate the result as shown above output images.

The Views

All the views and corresponding all the controller methods are created by scaffold command and they are available in the app/views/recipes directory.

How Scaffolding is Different?

If you have gone through the previous chapters, then you must have seen that we had created methods to list, show, delete and create data etc., but scaffolding does that job automatically.

Ruby on Rails - AJAX

Ajax stands for Asynchronous JavaScript and XML. Ajax is not a single technology; it is a suite of several technologies. Ajax incorporates the following −

  • XHTML for the markup of web pages
  • CSS for the styling
  • Dynamic display and interaction using the DOM
  • Data manipulation and interchange using XML
  • Data retrieval using XMLHttpRequest
  • JavaScript as the glue that meshes all this together

Ajax enables you to retrieve data for a web page without having to refresh the contents of the entire page. In the basic web architecture, the user clicks a link or submits a form. The form is submitted to the server, which then sends back a response. The response is then displayed for the user on a new page.

When you interact with an Ajax-powered web page, it loads an Ajax engine in the background. The engine is written in JavaScript and its responsibility is to both communicate with the web server and display the results to the user. When you submit data using an Ajax-powered form, the server returns an HTML fragment that contains the server's response and displays only the data that is new or changed as opposed to refreshing the entire page.

For a complete detail on AJAX you can go through our AJAX Tutorial

How Rails Implements Ajax

Rails has a simple, consistent model for how it implements Ajax operations. Once the browser has rendered and displayed the initial web page, different user actions cause it to display a new web page (like any traditional web application) or trigger an Ajax operation −

  • Some trigger fires − This trigger could be the user clicking on a button or link, the user making changes to the data on a form or in a field, or just a periodic trigger (based on a timer).

  • The web client calls the server − A JavaScript method, XMLHttpRequest, sends data associated with the trigger to an action handler on the server. The data might be the ID of a checkbox, the text in an entry field, or a whole form.

  • The server does processing − The server-side action handler ( Rails controller action )-- does something with the data and returns an HTML fragment to the web client.

  • The client receives the response − The client-side JavaScript, which Rails creates automatically, receives the HTML fragment and uses it to update a specified part of the current page's HTML, often the content of a <div> tag.

These steps are the simplest way to use Ajax in a Rails application, but with a little extra work, you can have the server return any kind of data in response to an Ajax request, and you can create custom JavaScript in the browser to perform more involved interactions.

AJAX Example

This example works based on scaffold, Destroy concept works based on ajax.

In this example, we will provide, list, show and create operations on ponies table. If you did not understand the scaffold technology then we would suggest you to go through the previous chapters first and then continue with AJAX on Rails.

Creating An Application

Let us start with the creation of an application It will be done as follows −

rails new ponies

The above command creates an application, now we need to call the app directory using with cd command. It will enter in to an application directory then we need to call a scaffold command. It will be done as follows −

rails generate scaffold Pony name:string profession:string

Above command generates the scaffold with name and profession column. We need to migrate the data base as follows command

rake db:migrate

Now Run the Rails application as follows command

rails s

Now open the web browser and call a url as http://localhost:3000/ponies/new, The output will be as follows

Ajax

Creating an Ajax

Now open app/views/ponies/index.html.erb with suitable text editors. Update your destroy line with :remote => true, :class => 'delete_pony'.At finally, it looks like as follows.

Ajax

Create a file, destroy.js.erb, put it next to your other .erb files (under app/views/ponies). It should look like this −

Ajax

Now enter the code as shown below in destroy.js.erb

$('.delete_pony').bind('ajax:success', function() {
   $(this).closest('tr').fadeOut();
});

Now Open your controller file which is placed at app/controllers/ponies_controller.rb and add the following code in destroy method as shown below −

# DELETE /ponies/1
# DELETE /ponies/1.json
def destroy
   @pony = Pony.find(params[:id])
   @pony.destroy
   
   respond_to do |format|
      format.html { redirect_to ponies_url }
      format.json { head :no_content }
      format.js   { render :layout => false }
   end
   
end

At finally controller page is as shown image.

Ajax

Now run an application, Output called from http://localhost:3000/ponies/new, it will looks like as following image

Ajax

Press on create pony button, it will generate the result as follows

Ajax

Now click on back button, it will show all pony created information as shown image

Ajax

Till now, we are working on scaffold, now click on destroy button, it will call a pop-up as shown below image, the pop-up works based on Ajax.

Ajax

If Click on ok button, it will delete the record from pony. Here I have clicked ok button. Final output will be as follows −

Ajax

Ruby on Rails - File Uploading

You may have a requirement in which you want your site visitors to upload a file on your server. Rails makes it very easy to handle this requirement. Now we will proceed with a simple and small Rails project.

As usual, let's start off with a new Rails application called testfile. Let's create the basic structure of the application by using simple rails command.

tp> rails new testfile

Before starting application development, we should install gem files as shown below −

gem install carrierwave
gem install bootstrap-sass

Open up your gemfile and add the following two gems at the bottom as shown in the following image −

GEM

After adding gems in the gem file, we need to run the following command on the console −

bundle install

Creating the Model

We need to create a model with two strings as name and attachment as shown below −

rails g model Resume name:string attachment:string

We need to create the database migration as shown below −

rake db:migrate

We need to generate the controller as shown below −

rails g controller Resumes index new create destroy

Great! Now we have the basic structure set up. Now we need to create an uploader. An Uploader came from carrierwave gem and it tells to carrierwave how to handle the files. In short, it contained all file processing functionalities. Run the command to create an uploader as shown below

rails g uploader attachment

Now open the resume model and call the uploader as shown below. Resume model has placed at app/models/resume.rb −

class Resume < ActiveRecord::Base
   mount_uploader :attachment, AttachmentUploader # Tells rails to use this uploader for this model.
   validates :name, presence: true # Make sure the owner's name is present.
end

Before working on controller, we need to modify our config/routes.db as shown below −

CarrierWaveExample::Application.routes.draw do
   resources :resumes, only: [:index, :new, :create, :destroy]
   root "resumes#index"
end

Lets us edit the controller as shown below.

class ResumesController < ApplicationController
   def index
      @resumes = Resume.all
   end
   
   def new
      @resume = Resume.new
   end
   
   def create
      @resume = Resume.new(resume_params)
      
      if @resume.save
         redirect_to resumes_path, notice: "The resume #{@resume.name} has been uploaded."
      else
         render "new"
      end
      
   end
   
   def destroy
      @resume = Resume.find(params[:id])
      @resume.destroy
      redirect_to resumes_path, notice:  "The resume #{@resume.name} has been deleted."
   end
   
   private
      def resume_params
      params.require(:resume).permit(:name, :attachment)
   end
   
end

Let's add bootstrap implementation in css file.css file could be in app/assets/stylesheets/resumes.css.scss

@import "bootstrap";

Now open up app/views/layouts/application.html.erb and add codes as shown below −

<!DOCTYPE html>
<html>
   
   <head>
      <title>Yoursite</title>
      <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
      <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
      <%= csrf_meta_tags %>
   </head>
   
   <body>
      <div class = "container" style = "padding-top:20px;">
         <%= yield %>
      </div>
   </body>

</html>

Now we need to set up index views as shown below −

<% if !flash[:notice].blank? %>
   <div class = "alert alert-info">
      <%= flash[:notice] %>
   </div>
<% end %>

<br />

<%= link_to "New Resume", new_resume_path, class: "btn btn-primary" %>
<br />
<br />

<table class = "table table-bordered table-striped">
   <thead>.
      <tr>
         <th>Name</th>
         <th>Download Link</th>
         <th> </th>
      </tr>
   </thead>
   
   <tbody>
      <% @resumes.each do |resume| %>
         
         <tr>
            <td><%= resume.name %></td>
            <td><%= link_to "Download Resume", resume.attachment_url %></td>
            <td><%= button_to "Delete",  resume, method: :delete, class: "btn btn-danger", confirm: "Are you sure that you wish to delete #{resume.name}?" %></td>
         </tr>
         
      <% end %>
   </tbody>
   
</table>

Now, lets edit new.html.erb and add our form code.

<% if !@resume.errors.empty? %>
   <div class = "alert alert-error">
      
      <ul>
         <% @resume.errors.full_messages.each do |msg| %>
            <li><%= msg %></li>
         <% end %>
      </ul>
      
   </div>
<% end %>

<div class = "well">
   <%= form_for @resume, html: { multipart: true } do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>
      <%= f.label :attachment %>
      <%= f.file_field :attachment %>
      <%= f.submit "Save", class: "btn btn-primary" %>
   <% end %>
</div>

Now start the server and visit http://localhost:3000. It will produce a screen similar to as follows −

Output

One last thing we need to do is filter the list of allowed filetypes. For that we need add simple code as shown below at app/uploaders/attachment_uploader.rb

class AttachmentUploader < CarrierWave::Uploader::Base
   storage :file
   
   def store_dir
      "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
   end
   
   def extension_white_list
      %w(pdf doc htm html docx)
   end
end

Now start the server and visit http://localhost:3000. Now input a wrong format; it will generate a wrong message as shown below −

Output Wrong

For a complete detail on File object, you need to go through the Ruby Reference Manual.

Ruby on Rails - Send Emails

Action Mailer is the Rails component that enables applications to send and receive emails. In this chapter, we will see how to send an email using Rails. Let’s start creating an emails project using the following command.

tp> rails new mailtest

This will create the required framework to proceed. Now, we will start with configuring the ActionMailer.

Action Mailer - Configuration

Following are the steps you have to follow to complete your configuration before proceeding with the actual work −

Go to the config folder of your emails project and open environment.rb file and add the following line at the bottom of this file.

config.action_mailer.delivery_method = :smtp

It tells ActionMailer that you want to use the SMTP server. You can also set it to be :sendmail if you are using a Unix-based operating system such as Mac OS X or Linux.

Add the following lines of code at the bottom of your environment.rb as well.

config.action_mailer.smtp_settings = {
   address:              'smtp.gmail.com',
   port:                 587,
   domain:               'example.com',
   user_name:            '<username>',
   password:             '<password>',
   authentication:       'plain',
   enable_starttls_auto: true  
}

Replace each hash value with proper settings for your Simple Mail Transfer Protocol (SMTP) server. You can take this information from your Internet Service Provider if you already don't know. You don't need to change port number 25 and authentication type if you are using a standard SMTP server.

You may also change the default email message format. If you prefer to send email in HTML instead of plain text format, add the following line to config/environment.rb as well −

ActionMailer::Base.default_content_type = "text/html"

ActionMailer::Base.default_content_type could be set to "text/plain", "text/html", and "text/enriched". The default value is "text/plain".

The next step will be to create a mailer

Generate a Mailer

Use the following command to generate a mailer as follows −

tp> cd emails
emails> rails generate mailer Usermailer

This will create a file user_mailer.rb in the appmailer directory. Check the content of this file as follows −

class Emailer < ActionMailer::Base
end

Let's create one method as follows −

class UserMailer < ApplicationMailer
   default from: 'notifications@example.com'
   
   def welcome_email(user)
      @user = user
      @url  = 'http://www.gmail.com'
      mail(to: @user.email, subject: 'Welcome to My Awesome Site')
   end
   
end
  • default Hash − This is a hash of default values for any email you send from this mailer. In this case we are setting the :from header to a value for all messages in this class. This can be overridden on a per-email basis

  • mail − The actual email message, we are passing the :to and :subject headers in.

Create a file called welcome_email.html.erb in app/views/user_mailer/. This will be the template used for the email, formatted in HTML −

<html>
   
   <head>
      <meta content = 'text/html; charset = UTF-8' http-equiv = 'Content-Type' />
   </head>
   
   <body>
      <h1>Welcome to example.com, <%= @user.name %></h1>
      
      <p>
         You have successfully signed up to example.com,your username is: 
         <%= @user.login %>.<br>
      </p>
      
      <p>
         To login to the site, just follow this link: 
         <%= @url %>.
      </p>
      
      <p>Thanks for joining and have a great day!</p>
      
   </body>
</html>

Next we will create a text part for this application as follow −

Welcome to example.com, <%= @user.name %>
===============================================
 
You have successfully signed up to example.com,
your username is: <%= @user.login %>.
 
To login to the site, just follow this link: <%= @url %>.
 
Thanks for joining and have a great day!

Calling the Mailer

First, let's create a simple User scaffold

$ bin/rails generate scaffold user name email login
$ bin/rake db:migrate

Action Mailer is nicely integrated with Active Job so you can send emails outside of the request-response cycle, so the user doesn't have to wait on it −

class UsersController < ApplicationController
   # POST /users
   # POST /users.json
   def create
   @user = User.new(params[:user])
   
      respond_to do |format|
         if @user.save
            # Tell the UserMailer to send a welcome email after save
            UserMailer.welcome_email(@user).deliver_later
            
            format.html { redirect_to(@user, notice: 'User was successfully created.') }
            format.json { render json: @user, status: :created, location: @user }
         else
            format.html { render action: 'new' }
            format.json { render json: @user.errors, status: :unprocessable_entity }
         end
         
      end
      
   end
end

Now, test your application by using http://127.0.0.1:3000/users/new. It displays the following screen and by using this screen, you will be able to send your message to anybody.

Send Email

This will send your message and will display the text message "Message sent successfully" and output as follow −

sent mail to kittuprasad700@gmail.com (2023.Sms)
[ActiveJob] [ActionMailler::DeliveryJob] [2cfde3c-260e-4a33-1a6ada13a9b] Date: Thu, 09 Jul 2015 11:44:05 +0530
From: notification@example.com
To: kittuprasad700@gmail.com
Message-Id: <559e112d63c57_f1031e7f23467@kiranPro.mail>
Subject: Welcome to My Awesome Site
Mime-Version: 1.0
Content-Type: multipart/alternative;
boundary="--mimepart_559e112d601c8_f1031e7f20233f5";
charset=UTF-8
Content-Transfer-Encoding:7bit

RESTful Web Services Tutorial

posted on June 8, 2021

tags:

What is REST architecture?

REST stands for REpresentational State Transfer. REST is web standards based architecture and uses HTTP Protocol. It revolves around resource where every component is a resource and a resource is accessed by a common interface using HTTP standard methods. REST was first introduced by Roy Fielding in 2000.

In REST architecture, a REST Server simply provides access to resources and REST client accesses and modifies the resources. Here each resource is identified by URIs/ global IDs. REST uses various representation to represent a resource like text, JSON, XML. JSON is the most popular one.

HTTP methods

Following four HTTP methods are commonly used in REST based architecture.

  • GET − Provides a read only access to a resource.

  • POST − Used to create a new resource.

  • DELETE − Used to remove a resource.

  • PUT − Used to update a existing resource or create a new resource.

Introduction to RESTFul web services

A web service is a collection of open protocols and standards used for exchanging data between applications or systems. Software applications written in various programming languages and running on various platforms can use web services to exchange data over computer networks like the Internet in a manner similar to inter-process communication on a single computer. This interoperability (e.g., between Java and Python, or Windows and Linux applications) is due to the use of open standards.

Web services based on REST Architecture are known as RESTful web services. These webservices uses HTTP methods to implement the concept of REST architecture. A RESTful web service usually defines a URI, Uniform Resource Identifier a service, provides resource representation such as JSON and set of HTTP Methods.

Creating RESTFul Webservice

In next chapters, we'll create a webservice say user management with following functionalities −

Sr.No. URI HTTP Method POST body Result
1 /UserService/users GET empty Show list of all the users.
2 /UserService/addUser POST JSON String Add details of new user.
3 /UserService/getUser/:id GET empty Show details of a user.

RESTful Web Services - Environment Setup

This tutorial will guide you on how to prepare a development environment to start your work with Jersey Framework to create RESTful Web Services. Jersey framework implements JAX-RS 2.0 API, which is a standard specification to create RESTful Web Services. This tutorial will also teach you how to setup JDK, Tomcat and Eclipse on your machine before you the Jersey Framework is setup.

Setup Java Development Kit (JDK)

You can download the latest version of SDK from Oracle's Java site − Java SE Downloads. You will find the instructions for installing JDK in the downloaded files. Follow the given instructions to install and configure the setup. Finally set the PATH and JAVA_HOME environment variables to refer to the directory that contains Java and Javac, typically java_install_dir/bin and java_install_dir respectively.

If you are running Windows and installed the JDK in C:jdk1.7.0_75, you would have to put the following line in your C:utoexec.bat file.

set PATH = C:jdk1.7.0_75in;%PATH% 
set JAVA_HOME = C:jdk1.7.0_75

Alternatively, on Windows NT/2000/XP, you could also right-click on My Computer → select Properties → then Advanced → then Environment Variables. Then, you would update the PATH value and press the OK button.

On Unix (Solaris, Linux, etc.), if the SDK is installed in /usr/local/jdk1.7.0_75 and you use the C Shell, you would put the following into your .cshrc file.

setenv PATH /usr/local/jdk1.7.0_75/bin:$PATH 
setenv JAVA_HOME /usr/local/jdk1.7.0_75

Alternatively, if you use an Integrated Development Environment (IDE) like Borland JBuilder, Eclipse, IntelliJ IDEA, or Sun ONE Studio, compile and run a simple program to confirm that the IDE knows where you installed Java, otherwise do proper setup as given document of the IDE.

Setup Eclipse IDE

All the examples in this tutorial have been written using the Eclipse IDE. So, I would suggest you should have the latest version of Eclipse installed on your machine.

To install Eclipse IDE, download the latest Eclipse binaries from https://www.eclipse.org/downloads/. Once you downloaded the installation, unpack the binary distribution to a convenient location. For example, in C:eclipse on windows, or /usr/local/eclipse on Linux/Unix and finally set the PATH variable appropriately.

Eclipse can be started by executing the following commands on a windows machine, or you can simply double click on eclipse.exe.

%C:eclipseeclipse.exe

Eclipse can be started by executing the following commands on Unix (Solaris, Linux, etc.) machine −

$/usr/local/eclipse/eclipse 

After a successful startup, if everything is fine, then your screen should display the following result −

Eclipse Home Page

Setup Jersey Framework Libraries

Now, if everything is fine, then you can proceed to setup the Jersey framework. Following are a few simple steps to download and install the framework on your machine.

  • Make a choice whether you want to install Jersey on Windows, or Unix and then proceed to the next step to download the .zip file for windows and then the .tz file for Unix.

  • Download the latest version of Jersey framework binaries from the following link – https://jersey.java.net/download.html.

  • At the time of writing this tutorial, I downloaded jaxrs-ri-2.17.zip on my Windows machine and when you unzip the downloaded file it will give you the directory structure inside E:jaxrs-ri-2.17jaxrs-ri as shown in the following screenshot.

Jaxrs Directory

You will find all the Jersey libraries in the directories C:jaxrs-ri-2.17jaxrs-rilib and dependencies in C:jaxrs-ri-2.17jaxrs-riext. Make sure you set your CLASSPATH variable on this directory properly otherwise you will face problem while running your application. If you are using Eclipse, then it is not required to set the CLASSPATH because all the settings will be done through Eclipse.

Setup Apache Tomcat

You can download the latest version of Tomcat from https://tomcat.apache.org/. Once you downloaded the installation, unpack the binary distribution into a convenient location. For example in C:pache-tomcat-7.0.59 on windows, or /usr/local/apache-tomcat-7.0.59 on Linux/Unix and set CATALINA_HOME environment variable pointing to the installation locations.

Tomcat can be started by executing the following commands on a windows machine, or you can simply double click on startup.bat.

%CATALINA_HOME%instartup.bat

or

C:pache-tomcat-7.0.59instartup.bat 

Tomcat can be started by executing the following commands on a Unix (Solaris, Linux, etc.) machine −

$CATALINA_HOME/bin/startup.sh

or

/usr/local/apache-tomcat-7.0.59/bin/startup.sh

After a successful startup, the default web applications included with Tomcat will be available by visiting http://localhost:8080/. If everything is fine then it should display the following result −

Tomcat

Further information about configuring and running Tomcat can be found in the documentation included on this page. This information can also be found on the Tomcat website − https://tomcat.apache.org.

Tomcat can be stopped by executing the following commands on a windows machine −

%CATALINA_HOME%inshutdown 

or

C:pache-tomcat-7.0.59inshutdown 

Tomcat can be stopped by executing the following commands on Unix (Solaris, Linux, etc.) machine −

$CATALINA_HOME/bin/shutdown.sh 

or

/usr/local/apache-tomcat-7.0.59/bin/shutdown.sh

Once you are done with this last step, you are ready to proceed for your first Jersey example which you will see in the next chapter.

RESTful Web Services - First Application

Let us start writing the actual RESTful web services with Jersey Framework. Before you start writing your first example using the Jersey Framework, you have to make sure that you have setup your Jersey environment properly as explained in the RESTful Web Services - Environment Setup chapter. Here, I am also assuming that you have a little working knowledge of Eclipse IDE.

So, let us proceed to write a simple Jersey Application which will expose a web service method to display the list of users.

Creating a Java Project

The first step is to create a Dynamic Web Project using Eclipse IDE. Follow the option File → New → Project and finally select the Dynamic Web Project wizard from the wizard list. Now name your project as UserManagement using the wizard window as shown in the following screenshot −

Dynamic Web Project Wizard

Once your project is created successfully, you will have the following content in your Project Explorer

Usermanagement Directories

Adding the Required Libraries

As a second step let us add Jersey Framework and its dependencies (libraries) in our project. Copy all jars from following directories of download jersey zip folder in WEB-INF/lib directory of the project.

  • jaxrs-ri-2.17jaxrs-ripi
  • jaxrs-ri-2.17jaxrs-riext
  • jaxrs-ri-2.17jaxrs-rilib

Now, right click on your project name UserManagement and then follow the option available in context menu − Build Path → Configure Build Path to display the Java Build Path window.

Now use Add JARs button available under Libraries tab to add the JARs present in WEBINF/lib directory.

Creating the Source Files

Now let us create the actual source files under the UserManagement project. First we need to create a package called com. To do this, right click on src in package explorer section and follow the option − New → Package.

Next we will create UserService.java, User.java,UserDao.java files under the com.yoursite package.

User.java

package com.yoursite;  

import java.io.Serializable;  
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
@XmlRootElement(name = "user") 

public class User implements Serializable {  
   private static final long serialVersionUID = 1L; 
   private int id; 
   private String name; 
   private String profession;  
   public User(){} 
    
   public User(int id, String name, String profession){  
      this.id = id; 
      this.name = name; 
      this.profession = profession; 
   }  
   public int getId() { 
      return id; 
   }  
   @XmlElement 
   public void setId(int id) { 
      this.id = id; 
   } 
   public String getName() { 
      return name; 
   } 
   @XmlElement
   public void setName(String name) { 
      this.name = name; 
   } 
   public String getProfession() { 
      return profession; 
   } 
   @XmlElement 
   public void setProfession(String profession) { 
      this.profession = profession; 
   }   
} 

UserDao.java

package com.yoursite;  

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException;  
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.util.ArrayList; 
import java.util.List;  

public class UserDao { 
   public List<User> getAllUsers(){ 
      
      List<User> userList = null; 
      try { 
         File file = new File("Users.dat"); 
         if (!file.exists()) { 
            User user = new User(1, "Mahesh", "Teacher"); 
            userList = new ArrayList<User>(); 
            userList.add(user); 
            saveUserList(userList); 
         } 
         else{ 
            FileInputStream fis = new FileInputStream(file); 
            ObjectInputStream ois = new ObjectInputStream(fis); 
            userList = (List<User>) ois.readObject(); 
            ois.close(); 
         } 
      } catch (IOException e) { 
         e.printStackTrace(); 
      } catch (ClassNotFoundException e) { 
         e.printStackTrace(); 
      }   
      return userList; 
   } 
   private void saveUserList(List<User> userList){ 
      try { 
         File file = new File("Users.dat"); 
         FileOutputStream fos;  
         fos = new FileOutputStream(file); 
         ObjectOutputStream oos = new ObjectOutputStream(fos); 
         oos.writeObject(userList); 
         oos.close(); 
      } catch (FileNotFoundException e) { 
         e.printStackTrace(); 
      } catch (IOException e) { 
         e.printStackTrace(); 
      } 
   }    
}

UserService.java

package com.yoursite;  

import java.util.List; 
import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType;  
@Path("/UserService") 

public class UserService {  
   UserDao userDao = new UserDao();  
   @GET 
   @Path("/users") 
   @Produces(MediaType.APPLICATION_XML) 
   public List<User> getUsers(){ 
      return userDao.getAllUsers(); 
   }  
}

There are two important points to be noted about the main program,

UserService.java

  • The first step is to specify a path for the web service using @Path annotation to the UserService.

  • The second step is to specify a path for the particular web service method using @Path annotation to method of UserService.

Creating the Web.xml configuration File

You need to create a Web xml Configuration file which is an XML file and is used to specify Jersey framework servlet for our application.

web.xml

<?xml version = "1.0" encoding = "UTF-8"?> 
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"  
   xmlns = "http://java.sun.com/xml/ns/javaee"  
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
   id = "WebApp_ID" version = "3.0"> 
   <display-name>User Management</display-name> 
   <servlet> 
      <servlet-name>Jersey RESTful Application</servlet-name> 
      <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> 
      <init-param> 
         <param-name>jersey.config.server.provider.packages</param-name> 
         <param-value>com.yoursite</param-value> 
      </init-param> 
   </servlet> 
   <servlet-mapping> 
      <servlet-name>Jersey RESTful Application</servlet-name> 
      <url-pattern>/rest/*</url-pattern> 
   </servlet-mapping>   
</web-app>

Deploying the Program

Once you are done with creating source and web configuration files, you are ready for this step which is compiling and running your program. To do this, using Eclipse, export your application as a war file and deploy the same in tomcat.

To create a WAR file using eclipse, follow the option File → export → Web → War File and finally select project UserManagement and destination folder. To deploy a war file in Tomcat, place the UserManagement.war in the Tomcat Installation Directory → webapps directory and start the Tomcat.

Running the Program

We are using Postman, a Chrome extension, to test our webservices.

Make a request to UserManagement to get list of all the users. Put http://localhost:8080/UserManagement/rest/UserService/users in POSTMAN with GET request and see the following result.

RESTful API, All users

Congratulations, you have created your first RESTful Application successfully.

RESTful Web Services - Resources

What is a Resource?

REST architecture treats every content as a resource. These resources can be Text Files, Html Pages, Images, Videos or Dynamic Business Data. REST Server simply provides access to resources and REST client accesses and modifies the resources. Here each resource is identified by URIs/ Global IDs. REST uses various representations to represent a resource where Text, JSON, XML. The most popular representations of resources are XML and JSON.

Representation of Resources

A resource in REST is a similar Object in Object Oriented Programming or is like an Entity in a Database. Once a resource is identified then its representation is to be decided using a standard format so that the server can send the resource in the above said format and client can understand the same format.

For example, in RESTful Web Services - First Application chapter, a user is a resource which is represented using the following XML format −

<user> 
   <id>1</id> 
   <name>Mahesh</name>
   <profession>Teacher</profession> 
</user> 

The same resource can be represented in JSON format as follows −

{ 
   "id":1, 
   "name":"Mahesh", 
   "profession":"Teacher" 
}

Good Resources Representation

REST does not impose any restriction on the format of a resource representation. A client can ask for JSON representation whereas another client may ask for XML representation of the same resource to the server and so on. It is the responsibility of the REST server to pass the client the resource in the format that the client understands.

Following are some important points to be considered while designing a representation format of a resource in RESTful Web Services.

  • Understandability − Both the Server and the Client should be able to understand and utilize the representation format of the resource.

  • Completeness − Format should be able to represent a resource completely. For example, a resource can contain another resource. Format should be able to represent simple as well as complex structures of resources.

  • Linkablity − A resource can have a linkage to another resource, a format should be able to handle such situations.

However, at present most of the web services are representing resources using either XML or JSON format. There are plenty of libraries and tools available to understand, parse, and modify XML and JSON data.

RESTful Web Services - Messages

RESTful Web Services make use of HTTP protocols as a medium of communication between client and server. A client sends a message in form of a HTTP Request and the server responds in the form of an HTTP Response. This technique is termed as Messaging. These messages contain message data and metadata i.e. information about message itself. Let us have a look on the HTTP Request and HTTP Response messages for HTTP 1.1.

HTTP Request

HTTP Request

An HTTP Request has five major parts −

  • Verb − Indicates the HTTP methods such as GET, POST, DELETE, PUT, etc.

  • URI − Uniform Resource Identifier (URI) to identify the resource on the server.

  • HTTP Version − Indicates the HTTP version. For example, HTTP v1.1.

  • Request Header − Contains metadata for the HTTP Request message as key-value pairs. For example, client (or browser) type, format supported by the client, format of the message body, cache settings, etc.

  • Request Body − Message content or Resource representation.

HTTP Response

HTTP Response

An HTTP Response has four major parts −

  • Status/Response Code − Indicates the Server status for the requested resource. For example, 404 means resource not found and 200 means response is ok.

  • HTTP Version − Indicates the HTTP version. For example HTTP v1.1.

  • Response Header − Contains metadata for the HTTP Response message as keyvalue pairs. For example, content length, content type, response date, server type, etc.

  • Response Body − Response message content or Resource representation.

Example

As we have explained in the RESTful Web Services - First Application chapter, let us put http://localhost:8080/UserManagement/rest/UserService/users in the POSTMAN with a GET request. If you click on the Preview button which is near the send button of Postman and then click on the Send button, you may see the following output.

HTTP Request/Response

Here you can see, the browser sent a GET request and received a response body as XML.

RESTful Web Services - Addressing

Addressing refers to locating a resource or multiple resources lying on the server. It is analogous to locate a postal address of a person.

Each resource in REST architecture is identified by its URI (Uniform Resource Identifier). A URI is of the following format −

<protocol>://<service-name>/<ResourceType>/<ResourceID>

Purpose of an URI is to locate a resource(s) on the server hosting the web service. Another important attribute of a request is VERB which identifies the operation to be performed on the resource. For example, in RESTful Web Services - First Application chapter, the URI is http://localhost:8080/UserManagement/rest/UserService/users and the VERB is GET.

Constructing a Standard URI

The following are important points to be considered while designing a URI −

  • Use Plural Noun − Use plural noun to define resources. For example, we've used users to identify users as a resource.

  • Avoid using spaces − Use underscore (_) or hyphen (-) when using a long resource name. For example, use authorized_users instead of authorized%20users.

  • Use lowercase letters − Although URI is case-insensitive, it is a good practice to keep the url in lower case letters only.

  • Maintain Backward Compatibility − As Web Service is a public service, a URI once made public should always be available. In case, URI gets updated, redirect the older URI to a new URI using the HTTP Status code, 300.

  • Use HTTP Verb − Always use HTTP Verb like GET, PUT and DELETE to do the operations on the resource. It is not good to use operations name in the URI.

Example

Following is an example of a poor URI to fetch a user.

http://localhost:8080/UserManagement/rest/UserService/getUser/1 

Following is an example of a good URI to fetch a user.

http://localhost:8080/UserManagement/rest/UserService/users/1

RESTful Web Services - Methods

As we have discussed in the earlier chapters that RESTful Web Service uses a lot of HTTP verbs to determine the operation to be carried out on the specified resource(s). The following table states the examples of the most commonly used HTTP Verbs.

Sr.No. HTTP Method, URI and Operation
1

GET

http://localhost:8080/UserManagement/rest/UserService/users

Gets the list of users.

(Read Only)

2

GET

http://localhost:8080/UserManagement/rest/UserService/users/1

Gets the User of Id 1

(Read Only)

3

PUT

http://localhost:8080/UserManagement/rest/UserService/users/2

Inserts User with Id 2

(Idempotent)

4

POST

http://localhost:8080/UserManagement/rest/UserService/users/2

Updates the User with Id 2

(N/A)

5

DELETE

http://localhost:8080/UserManagement/rest/UserService/users/1

Deletes the User with Id 1

(Idempotent)

6

OPTIONS

http://localhost:8080/UserManagement/rest/UserService/users

Lists out the supported operations in a web service.

(Read Only)

7

HEAD

http://localhost:8080/UserManagement/rest/UserService/users

Returns the HTTP Header only, no Body.

(Read Only)

The following points are to be considered.

  • GET operations are read only and are safe.

  • PUT and DELETE operations are idempotent, which means their result will always be the same, no matter how many times these operations are invoked.

  • PUT and POST operation are nearly the same with the difference lying only in the result where the PUT operation is idempotent and POST operation can cause a different result.

Example

Let us update an Example created in the RESTful Web Services - First Application chapter to create a Web service which can perform CRUD (Create, Read, Update, Delete) operations. For simplicity, we have used a file I/O to replace Database operations.

Let us update the User.java, UserDao.java and UserService.java files under the com.yoursite package.

User.java

package com.yoursite; 

import java.io.Serializable;  
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
@XmlRootElement(name = "user") 

public class User implements Serializable {  
   private static final long serialVersionUID = 1L; 
   private int id; 
   private String name; 
   private String profession;  
   public User(){}  
   
   public User(int id, String name, String profession){ 
      this.id = id; 
      this.name = name; 
      this.profession = profession; 
   }  
    
   public int getId() {
      return id; 
   } 
   @XmlElement 
   public void setId(int id) { 
      this.id = id; 
   } 
   public String getName() { 
      return name; 
   } 
   @XmlElement 
      public void setName(String name) { 
      this.name = name; 
   } 
   public String getProfession() { 
      return profession; 
   } 
   @XmlElement 
   public void setProfession(String profession) { 
      this.profession = profession; 
   }   
   @Override 
   public boolean equals(Object object){ 
      if(object == null){ 
         return false; 
      }else if(!(object instanceof User)){ 
         return false; 
      }else { 
         User user = (User)object; 
         if(id == user.getId() 
            && name.equals(user.getName()) 
            && profession.equals(user.getProfession())){ 
               return true; 
         }
      } 
      return false; 
   }  
} 

UserDao.java

package com.yoursite;  

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.util.ArrayList; 
import java.util.List;  

public class UserDao { 
   public List<User> getAllUsers(){ 
      List<User> userList = null; 
      try { 
         File file = new File("Users.dat"); 
         if (!file.exists()) { 
            User user = new User(1, "Mahesh", "Teacher"); 
            userList = new ArrayList<User>(); 
            userList.add(user); 
            saveUserList(userList);   
         } 
         else{ 
            FileInputStream fis = new FileInputStream(file); 
            ObjectInputStream ois = new ObjectInputStream(fis); 
            userList = (List<User>) ois.readObject(); 
            ois.close(); 
         }
      } catch (IOException e) { 
         e.printStackTrace(); 
      } catch (ClassNotFoundException e) { 
         e.printStackTrace(); 
      }   
      return userList; 
   }  
   public User getUser(int id){ 
      List<User> users = getAllUsers();  
      for(User user: users){ 
         if(user.getId() == id){ 
            return user; 
         } 
      } 
      return null; 
   }  
   public int addUser(User pUser){ 
      List<User> userList = getAllUsers(); 
      boolean userExists = false; 
      for(User user: userList){ 
         if(user.getId() == pUser.getId()){ 
            userExists = true; 
            break; 
         } 
      }   
      if(!userExists){ 
         userList.add(pUser); 
         saveUserList(userList); 
         return 1; 
      } 
      return 0; 
   }
   public int updateUser(User pUser){ 
      List<User> userList = getAllUsers();  
      for(User user: userList){ 
         if(user.getId() == pUser.getId()){ 
            int index = userList.indexOf(user);    
            userList.set(index, pUser); 
            saveUserList(userList); 
            return 1; 
         } 
      }   
      return 0; 
   }  
   public int deleteUser(int id){ 
      List<User> userList = getAllUsers();  
      for(User user: userList){ 
         if(user.getId() == id){ 
            int index = userList.indexOf(user);    
            userList.remove(index); 
            saveUserList(userList); 
            return 1;    
         } 
      }   
      return 0; 
   }  
   private void saveUserList(List<User> userList){ 
      try { 
         File file = new File("Users.dat"); 
         FileOutputStream fos;  
         fos = new FileOutputStream(file);
         ObjectOutputStream oos = new ObjectOutputStream(fos);   
         oos.writeObject(userList); 
         oos.close(); 
      } catch (FileNotFoundException e) { 
         e.printStackTrace(); 
      } catch (IOException e) { 
         e.printStackTrace(); 
      } 
   } 
}

UserService.java

package com.yoursite;  

import java.io.IOException; 
import java.util.List;  
import javax.servlet.http.HttpServletResponse; 
import javax.ws.rs.Consumes; 
import javax.ws.rs.DELETE; 
import javax.ws.rs.FormParam; 
import javax.ws.rs.GET; 
import javax.ws.rs.OPTIONS; 
import javax.ws.rs.POST; 
import javax.ws.rs.PUT; 
import javax.ws.rs.Path; 
import javax.ws.rs.PathParam; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.MediaType;  
@Path("/UserService") 

public class UserService { 
  
   UserDao userDao = new UserDao(); 
   private static final String SUCCESS_RESULT = "<result>success</result>"; 
   private static final String FAILURE_RESULT = "<result>failure</result>";  
   @GET 
   @Path("/users") 
   @Produces(MediaType.APPLICATION_XML) 
   public List<User> getUsers(){ 
      return userDao.getAllUsers(); 
   }  
   @GET 
   @Path("/users/{userid}") 
   @Produces(MediaType.APPLICATION_XML) 
   public User getUser(@PathParam("userid") int userid){ 
      return userDao.getUser(userid); 
   }  
   @PUT 
   @Path("/users") 
   @Produces(MediaType.APPLICATION_XML) 
   @Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
   public String createUser(@FormParam("id") int id, 
      @FormParam("name") String name, 
      @FormParam("profession") String profession, 
      @Context HttpServletResponse servletResponse) throws IOException{ 
      User user = new User(id, name, profession); 
      int result = userDao.addUser(user); 
      if(result == 1){ 
         return SUCCESS_RESULT; 
      } 
      return FAILURE_RESULT; 
   }  
   @POST 
   @Path("/users")  
   @Produces(MediaType.APPLICATION_XML)
   @Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
   public String updateUser(@FormParam("id") int id, 
      @FormParam("name") String name, 
      @FormParam("profession") String profession, 
      @Context HttpServletResponse servletResponse) throws IOException{ 
      User user = new User(id, name, profession); 
      int result = userDao.updateUser(user); 
      if(result == 1){ 
         return SUCCESS_RESULT; 
      } 
      return FAILURE_RESULT; 
   }  
   @DELETE 
   @Path("/users/{userid}") 
   @Produces(MediaType.APPLICATION_XML) 
   public String deleteUser(@PathParam("userid") int userid){ 
      int result = userDao.deleteUser(userid); 
      if(result == 1){ 
         return SUCCESS_RESULT; 
      } 
      return FAILURE_RESULT; 
   }  
   @OPTIONS 
   @Path("/users") 
   @Produces(MediaType.APPLICATION_XML) 
   public String getSupportedOperations(){ 
      return "<operations>GET, PUT, POST, DELETE</operations>"; 
   } 
}

Now using Eclipse, export your application as a WAR File and deploy the same in Tomcat. To create a WAR file using eclipse, follow this path – File → export → Web → War File and finally select project UserManagement and the destination folder. To deploy a WAR file in Tomcat, place the UserManagement.war in the Tomcat Installation Directory → webapps directory and the start Tomcat.

Testing the Web Service

Jersey provides APIs to create a Web Service Client to test web services. We have created a sample test class WebServiceTester.java under the com.yoursite package in the same project.

WebServiceTester.java

package com.yoursite;  

import java.util.List; 
import javax.ws.rs.client.Client; 
import javax.ws.rs.client.ClientBuilder; 
import javax.ws.rs.client.Entity; 
import javax.ws.rs.core.Form; 
import javax.ws.rs.core.GenericType; 
import javax.ws.rs.core.MediaType;  

public class WebServiceTester  {  
   private Client client; 
   private String REST_SERVICE_URL = "
   http://localhost:8080/UserManagement/rest/UserService/users"; 
   private static final String SUCCESS_RESULT = "<result>success</result>"; 
   private static final String PASS = "pass"; 
   private static final String FAIL = "fail";  
   private void init(){ 
      this.client = ClientBuilder.newClient(); 
   }  
   public static void main(String[] args){ 
      WebServiceTester tester = new WebServiceTester(); 
      //initialize the tester 
      tester.init(); 
      //test get all users Web Service Method 
      tester.testGetAllUsers(); 
      //test get user Web Service Method  
      tester.testGetUser();
      //test update user Web Service Method 
      tester.testUpdateUser(); 
      //test add user Web Service Method 
      tester.testAddUser(); 
      //test delete user Web Service Method 
      tester.testDeleteUser(); 
   } 
   //Test: Get list of all users 
   //Test: Check if list is not empty 
   private void testGetAllUsers(){ 
      GenericType<List<User>> list = new GenericType<List<User>>() {}; 
      List<User> users = client 
         .target(REST_SERVICE_URL) 
         .request(MediaType.APPLICATION_XML) 
         .get(list); 
      String result = PASS; 
      if(users.isEmpty()){ 
         result = FAIL; 
      } 
      System.out.println("Test case name: testGetAllUsers, Result: " + result ); 
   } 
   //Test: Get User of id 1 
   //Test: Check if user is same as sample user 
   private void testGetUser(){ 
      User sampleUser = new User(); 
      sampleUser.setId(1);  
      User user = client 
         .target(REST_SERVICE_URL) 
         .path("/{userid}") 
         .resolveTemplate("userid", 1) 
         .request(MediaType.APPLICATION_XML) 
         .get(User.class); 
      String result = FAIL; 
      if(sampleUser != null && sampleUser.getId() == user.getId()){
         result = PASS; 
      } 
      System.out.println("Test case name: testGetUser, Result: " + result ); 
   } 
   //Test: Update User of id 1 
   //Test: Check if result is success XML. 
   private void testUpdateUser(){ 
      Form form = new Form(); 
      form.param("id", "1"); 
      form.param("name", "suresh"); 
      form.param("profession", "clerk");  
      String callResult = client 
         .target(REST_SERVICE_URL) 
         .request(MediaType.APPLICATION_XML) 
         .post(Entity.entity(form, 
         MediaType.APPLICATION_FORM_URLENCODED_TYPE), 
         String.class); 
      String result = PASS; 
      if(!SUCCESS_RESULT.equals(callResult)){ 
         result = FAIL; 
      }  
      System.out.println("Test case name: testUpdateUser, Result: " + result); 
   } 
   //Test: Add User of id 2 
   //Test: Check if result is success XML. 
   private void testAddUser(){ 
      Form form = new Form(); 
      form.param("id", "2"); 
      form.param("name", "naresh"); 
      form.param("profession", "clerk");  
      String callResult = client 
         .target(REST_SERVICE_URL) 
         .request(MediaType.APPLICATION_XML) 
         .put(Entity.entity(form, 
         MediaType.APPLICATION_FORM_URLENCODED_TYPE), 
         String.class); 
    
      String result = PASS; 
      if(!SUCCESS_RESULT.equals(callResult)){ 
         result = FAIL; 
      }  
      System.out.println("Test case name: testAddUser, Result: " + result ); 
   } 
   //Test: Delete User of id 2 
   //Test: Check if result is success XML. 
   private void testDeleteUser(){ 
      String callResult = client 
         .target(REST_SERVICE_URL) 
         .path("/{userid}") 
         .resolveTemplate("userid", 2) 
         .request(MediaType.APPLICATION_XML) 
         .delete(String.class);  
      String result = PASS; 
      if(!SUCCESS_RESULT.equals(callResult)){ 
         result = FAIL; 
      } 
      System.out.println("Test case name: testDeleteUser, Result: " + result); 
   } 
}

Now run the tester using Eclipse. Right click on the file and follow the option Run as → Java Application. You will see the following result in the Eclipse console −

Test case name: testGetAllUsers, Result: pass 
Test case name: testGetUser, Result: pass 
Test case name: testUpdateUser, Result: pass 
Test case name: testAddUser, Result: pass 
Test case name: testDeleteUser, Result: pass 

RESTful Web Services - Statelessness

As per the REST architecture, a RESTful Web Service should not keep a client state on the server. This restriction is called Statelessness. It is the responsibility of the client to pass its context to the server and then the server can store this context to process the client's further request. For example, session maintained by server is identified by session identifier passed by the client.

RESTful Web Services should adhere to this restriction. We have seen this in the RESTful Web Services - Methods chapter, that the web service methods are not storing any information from the client they are invoked from.

Consider the following URL −

https://localhost:8080/UserManagement/rest/UserService/users/1

If you hit the above url using your browser or using a java based client or using Postman, result will always be the User XML whose Id is 1 because the server does not store any information about the client.

<user> 
   <id>1</id> 
   <name>mahesh</name> 
   <profession>1</profession> 
</user>

Advantages of Statelessness

Following are the benefits of statelessness in RESTful Web Services −

  • Web services can treat each method request independently.

  • Web services need not maintain the client's previous interactions. It simplifies the application design.

  • As HTTP is itself a statelessness protocol, RESTful Web Services work seamlessly with the HTTP protocols.

Disadvantages of Statelessness

Following are the disadvantages of statelessness in RESTful Web Services −

  • Web services need to get extra information in each request and then interpret to get the client's state in case the client interactions are to be taken care of.

RESTful Web Services - Caching

Caching refers to storing the server response in the client itself, so that a client need not make a server request for the same resource again and again. A server response should have information about how caching is to be done, so that a client caches the response for a time-period or never caches the server response.

Following are the headers which a server response can have in order to configure a client's caching −

Sr.No. Header & Description

1

Date

Date and Time of the resource when it was created.

2

Last Modified

Date and Time of the resource when it was last modified.

3

Cache-Control

Primary header to control caching.

4

Expires

Expiration date and time of caching.

5

Age

Duration in seconds from when resource was fetched from the server.

Cache-Control Header

Following are the details of a Cache-Control header −

Sr.No. Directive & Description

1

Public

Indicates that resource is cacheable by any component.

2

Private

Indicates that resource is cacheable only by the client and the server, no intermediary can cache the resource.

3

no-cache/no-store

Indicates that a resource is not cacheable.

4

max-age

Indicates the caching is valid up to max-age in seconds. After this, client has to make another request.

5

must-revalidate

Indication to server to revalidate resource if max-age has passed.

Best Practices

  • Always keep static contents like images, CSS, JavaScript cacheable, with expiration date of 2 to 3 days.

  • Never keep expiry date too high.

  • Dynamic content should be cached for a few hours only.

Best practices for Cache-Control

RESTful Web Services - Security

As RESTful Web Services work with HTTP URL Paths, it is very important to safeguard a RESTful Web Service in the same manner as a website is secured.

Following are the best practices to be adhered to while designing a RESTful Web Service −

  • Validation − Validate all inputs on the server. Protect your server against SQL or NoSQL injection attacks.

  • Session Based Authentication − Use session based authentication to authenticate a user whenever a request is made to a Web Service method.

  • No Sensitive Data in the URL − Never use username, password or session token in a URL, these values should be passed to Web Service via the POST method.

  • Restriction on Method Execution − Allow restricted use of methods like GET, POST and DELETE methods. The GET method should not be able to delete data.

  • Validate Malformed XML/JSON − Check for well-formed input passed to a web service method.

  • Throw generic Error Messages − A web service method should use HTTP error messages like 403 to show access forbidden, etc.

HTTP Code

Sr.No. HTTP Code & Description

1

200

OK − shows success.

2

201

CREATED − when a resource is successfully created using POST or PUT request. Returns link to the newly created resource using the location header.

3

204

NO CONTENT − when response body is empty. For example, a DELETE request.

4

304

NOT MODIFIED − used to reduce network bandwidth usage in case of conditional GET requests. Response body should be empty. Headers should have date, location, etc.

5

400

BAD REQUEST − states that an invalid input is provided. For example, validation error, missing data.

6

401

UNAUTHORIZED − states that user is using invalid or wrong authentication token.

7

403

FORBIDDEN − states that the user is not having access to the method being used. For example, Delete access without admin rights.

8

404

NOT FOUND − states that the method is not available.

9

409

CONFLICT − states conflict situation while executing the method. For example, adding duplicate entry.

10

500

INTERNAL SERVER ERROR − states that the server has thrown some exception while executing the method.

RESTful Web Services - Java (JAX-RS)

JAX-RS stands for JAVA API for RESTful Web Services. JAX-RS is a JAVA based programming language API and specification to provide support for created RESTful Web Services. Its 2.0 version was released on the 24th May 2013. JAX-RS uses annotations available from Java SE 5 to simplify the development of JAVA based web services creation and deployment. It also provides supports for creating clients for RESTful Web Services.

Specifications

Following are the most commonly used annotations to map a resource as a web service resource.

Sr.No. Annotation & Description

1

@Path

Relative path of the resource class/method.

2

@GET

HTTP Get request, used to fetch resource.

3

@PUT

HTTP PUT request, used to update resource.

4

@POST

HTTP POST request, used to create a new resource.

5

@DELETE

HTTP DELETE request, used to delete resource.

6

@HEAD

HTTP HEAD request, used to get status of method availability.

7

@Produces

States the HTTP Response generated by web service. For example, APPLICATION/XML, TEXT/HTML, APPLICATION/JSON etc.

8

@Consumes

States the HTTP Request type. For example, application/x-www-formurlencoded to accept form data in HTTP body during POST request.

9

@PathParam

Binds the parameter passed to the method to a value in path.

10

@QueryParam

Binds the parameter passed to method to a query parameter in the path.

11

@MatrixParam

Binds the parameter passed to the method to a HTTP matrix parameter in path.

12

@HeaderParam

Binds the parameter passed to the method to a HTTP header.

13

@CookieParam

Binds the parameter passed to the method to a Cookie.

14

@FormParam

Binds the parameter passed to the method to a form value.

15

@DefaultValue

Assigns a default value to a parameter passed to the method.

16

@Context

Context of the resource. For example, HTTPRequest as a context.

What are the most secure cloud storage solutions?

posted on June 8, 2021

tags:

Using a cloud storage service can be very helpful, but what is the best cloud storage

service available?

Today, all of us have ever used a cloud storage service. As you surely know, this service is a kind of hard drive in which you can store different files, but instead of having a physical format, it has a virtual format, it is on the Internet.

That means that if you use a cloud storage service, you can access it from any device with Internet access, as long as you have the access data.

Besides being a very practical way to work on the same document from different devices, or to be able to view your photos wherever you are, it is also a highly recommended way to make backup copies.

So, it is clear to us that using a cloud storage service is highly recommended, but ... which service should I choose?

If you have had time to find some information about the different cloud storage services, you will have realized that there are too many. This can make choosing the right service for you difficult.

Your choice will depend on many factors: space you want, type of extra tools you prefer and, above all, the price. For this reason, in this article we explain more about our favorite cloud storage services, hoping to help you choose.

1. Google Drive

Maybe Google Drive is the most well known distributed storage stage today. We definitely realize that all that identified with Google has an enormous number of clients. Likewise, for this situation it offers extremely intriguing capacities, just as similarity with numerous stages and working frameworks, it is additionally vital to say that there is no restriction of synchronized gadgets, we will essentially have a constraint of extra room in the cloud.

Beyond the payment plans that are available , we can have 15 GB for free. A limit that will permit us to have records, reinforcement duplicates and keep our significant archives consistently accessible. If you are keen on installment designs, the costs are as per the following:

100GB of capacity: € 1.99 each month or € 19.99 each year.

200GB of capacity: € 2.99 each month or € 29.99 each year.

2TB of capacity: € 9.99 each month or € 99.99 each year.

10TB of storage: € 99.99 per month

20TB of storage: € 199.99 per month

30TB of storage: € 299.99 per month

Some vital highlights of Google One (the paid variant of Google Drive) are that it will permit us to share our extra room with up to 5 different individuals of our family. That is, if we decide to buy the 200GB storage subscription, we can add family members to use this storage capacity, exceeding the 15GB we have for free.

We figure the 200GB stockpiling alternative to impart to relatives is probably the best arrangement out there today, in spite of the fact that in the event that you needn't bother with that much, you can generallys go for the 100GB storage version.

2. Dropbox

Dropbox is a classic. We are confronting a well known distributed storage administration, which is available on numerous stages and has countless clients around the planet. It does not stand out especially for its free storage size, which is 2 GB , but it does have different payment plans that are very interesting for users. Additionally, there are generally strategies to acquire capacity without paying.

In the event that you are interested in the Dropbox payment plans, the price of the subscription for individuals includes 2TB of cloud storage for € 9.99 per month (but if you do it with the annual payment), if you want to pay monthly the price goes up to € 11.99 per month. Some vital highlights of Dropbox in its paid variant are the accompanying:

It allows you to synchronize files and folders on as many devices as you want, we have no limitation as it does with the free version.

We can make shared organizers and connections, furthermore, it permits you to send records up to 2GB in size with Dropbox Transfer

    It allows to recover accounts from 30 days ago, and also allows a file history of the last 30 days.
    We have offline folders for mobile phones, ideal for synchronizing them over Wi-Fi and having them offline.
    It permits the distant cancellation of records, and the pursuit of text in the various archives that we have.

As you have seen, Dropbox is a generally excellent help. It also offers a family plan to include up to 6 users. They also have rates for 3 and 5 TB professionals, with other characteristics such as a 180-day history.

3. OneDrive

Microsoft's alternative is called OneDrive . As in the past case, it doesn't stand apart particularly for its free stockpiling, since it offers just 5 GB . In any case, it is a choice broadly utilized by clients and it likewise has numerous plans with which we can extend the limit. Particularly for the individuals who use Outlook as their email supplier, OneDrive is an alternative to consider.

On account of Microsoft's paid plans, there are a few plans that consolidate Office 365, which is truly uplifting news in the event that you utilize Microsoft's Office suite.

100GB of OneDrive storage only: € 2 per month

Office 365 Home: 6TB of capacity in OneDrive and incorporates Office for PC and Mac (Word, Excel, PowerPoint and Outlook), permits you to add an aggregate of 6 individuals to this record, the cost is € 99 every year or € 10 every month.

We recommend you access the official website of OneDrive plans where you will find all its features.

4. Box

Less notable is the Box distributed storage stage . It is focused on both private clients and organizations. It offers 10 GB free with a greatest size for every document of 250MB, notwithstanding a progression of plans with which to grow the limit. One of the features is that they underscore security. We definitely realize that it is a factor to be considered by clients on the organization.

Box has diverse truly fascinating estimating plans, focused on both home clients and organizations. On the off chance that you choose to get a field-tested strategy, the yearly membership is intriguing since it has a 5% markdown contrasted with the "typical" cost.

The cost of the "Individual Pro" membership is € 9 every month, and incorporates 100GB of capacity with a greatest size for each document of 5GB. With this arrangement it does not merit utilizing Box, it is vastly improved to go to any of the past ones.

5. NextCloud

NextCloud is also quite popular . It is a distributed storage administration that has numerous clients and offers various choices to synchronize our documents on the Internet. It is additionally uncommonly intended for organizations and client gatherings. It has various capacity designs that can be fascinating.

NextCloud is only the file and folder synchronization software, if you install it on a remote VPS server, you will have the maximum capacity of the contracted VPS server. The equivalent occurs in the event that you introduce it on a NAS worker, that is, Nextcloud is a private cloud, where you should mount everything, except it is strongly suggested on the off chance that you need opportunity while picking a worker and/or specialist organization

6. pCloud

pCloud has applications for various frameworks, for example, Windows, Linux, macOS, Android or iOS, among others. It is an elective that has acquired notoriety lately. It offers various designs for putting away documents on the organization.

pCloud has two annual payment plans, but there is a very interesting plan that is for life. The final payment plans are as follows:

500GB of storage for € 48 per year. It incorporates the capacity to impart connections to others, and even permits a 30-day reuse receptacle.

2TB of capacity for € 96 every year. It incorporates the capacity to impart connections to others, and even permits a 30-day reuse canister..

There are two other very interesting plans that are "for life", with a single payment and under the same conditions as the previous ones.

500GB of storage for € 175 one-time.

2TB of storage for € 350 one time.

If you plan to use this service for more than 3 years, it is clear that it is worth buying the pCloud "for life" plan.

7. Mega

Mega is a standout amongst other known other options and it has more stockpiling accessible free of charge. It permits you to have up to 50 GB without paying anything. It likewise offers numerous downloads and a genuinely complete substance the board. This is quite possibly the most utilized choices by clients. Doubtlessly it is intriguing to have weighty reinforcements and have all the documents consistently accessible from anyplace.

Mega likewise has serious and intriguing installment plans in the event that you utilize this help. These prices are very interesting if you need a large amount of storage in the cloud, since for € 20 per month you can have 8TB of storage.

Compared to other services, if you need a lot of storage space, Mega is the best you can hire, if you need little space it is very on par with others

8. Amazon Drive plans

Prime : one of the options is if we are Prime users. In this case we will have unlimited and free storage for photographs. They also give us 5 GB to save videos.

100GB - A top and very popular option is 100GB. It costs € 1.99 per month (€ 19.99 per year) and is ideal for users who want to have a backup of their images and videos without worrying about storage. With that capacity we have plenty for a common user.

1 TB : For those looking for something higher, Amazon Drive also offers a rate of € 9.99 per month (€ 99.99 per year) that has 1 TB of storage. It is perfect to have a large number of files always available on the Internet, without worrying about losing important documents.

2 TB : Amazon Drive also has its version of 2 TB of storage in the cloud. In this case the price is € 19.99 per month (€ 199.98 per year).

It offers many more options ranging from 3TB to 30TB. In this case, you have to pay annually and it goes from € 299.97 for the 3 TB to € 2999.70 for the highest, the 30 TB one.

RxJS Tutorial

posted on June 7, 2021

tags:

This chapter deals with information about features, advantages and disadvantages of RxJS. Here, we will also learn when to use RxJS.

The full form of RxJS is Reactive Extension for Javascript. It is a javascript library that uses observables to work with reactive programming that deals with asynchronous data calls, callbacks and event-based programs. RxJS can be used with other Javascript libraries and frameworks. It is supported by javascript and also with typescript.

What is RxJS?

As per the official website of RxJS, it is defined as a library for composing asynchronous and event-based programs by using observable sequences. It provides one core type, the Observable, satellite types (Observer, Schedulers, Subjects) and operators inspired by Array#extras (map, filter, reduce, every, etc.) to allow handling asynchronous events as collections.

Features of RxJS

In RxJS, the following concepts takes care of handling the async task −

Observable

An observable is a function that creates an observer and attaches it to the source where values are expected, for example, clicks, mouse events from a dom element or an Http request, etc.

Observer

It is an object with next(), error() and complete() methods, that will get called when there is interaction to the with the observable i.e. the source interacts for an example button click, Http request, etc.

Subscription

When the observable is created, to execute the observable we need to subscribe to it. It can also be used to cancel the execution.

Operators

An operator is a pure function that takes in observable as input and the output is also an observable.

Subject

A subject is an observable that can multicast i.e. talk to many observers. Consider a button with an event listener, the function attached to the event using addlistener is called every time the user clicks on the button similar functionality goes for subject too.

Schedulers

A scheduler controls the execution of when the subscription has to start and notified.

When to use RxJS?

If your project consists of lots of async task handling than RxJS is a good choice. It is loaded by default with the Angular project.

Advantages of using RxJS

The following are the advantages of using RxJS −

  • RxJS can be used with other Javascript libraries and frameworks. It is supported by javascript and also with typescript. Few examples are Angular, ReactJS, Vuejs, nodejs etc.

  • RxJS is an awesome library when it comes to the handling of async tasks.RxJS uses observables to work with reactive programming that deals with asynchronous data calls, callbacks and event-based programs.

  • RxJS offers a huge collection of operators in mathematical, transformation, filtering, utility, conditional, error handling, join categories that makes life easy when used with reactive programming.

Disadvantages of using RxJS

The following are the disadvantages of using RxJS −

  • Debugging the code with observables is little difficult.

  • As you start to use Observables, you can end up your full code wrapped under the observables.

RxJS - Environment Setup

In this chapter, we are going to install RxJS. To work with RxJS, we need the following setup −

  • NodeJS
  • Npm
  • RxJS package installation

NODEJS and NPM Installation

It is very easy to install RxJS using npm. You need to have nodejs and npm installed on your system. To verify if NodeJS and npm is installed on your system, try to execute the following command in your command prompt.

E:>node -v && npm -v
v10.15.1
6.4.1

In case you are getting the version, it means nodejs and npm is installed on your system and the version is 10 and 6 right now on the system.

If it does not print anything, install nodejs on your system. To install nodejs, go to the homepage https://nodejs.org/en/download/ of nodejs and install the package based on your OS.

The download page of nodejs will look like the following −

NodeJS

Based on your OS, install the required package. Once nodejs is installed, npm will also be installed along with it. To check if npm is installed or not, type npm –v in the terminal. It should display the version of the npm.

RxJS Package Installation

To start with RxJS installation, first create a folder called rxjsproj/ where we will practice all RxJS examples.

Once the folder rxjsproj/ is created, run command npm init, for project setup as shown below

E:>mkdir rxjsproj
E:>cd rxjsproj
E:
xjsproj>npm init

Npm init command will ask few questions during execution, just press enter and proceed. Once the execution of npm init is done, it will create package.json inside rxjsproj/ as shown below −

rxjsproj/
   package.json

Now you can install rxjs using below command −

npm install ---save-dev rxjs
E:
xjsproj>npm install --save-dev rxjs
npm notice created a lockfile as package-lock.json. You should commit this file.

npm WARN rxjsproj@1.0.0 No description
npm WARN rxjsproj@1.0.0 No repository field.

+ rxjs@6.5.3
added 2 packages from 7 contributors and audited 2 packages in 21.89s
found 0 vulnerabilities

We are done with RxJS installation. Let us now try to use RxJS, for that create a folder src/ inside rxjsproj/

So, now, we will have the folder structure as shown below −

rxjsproj/
   node_modules/
   src/
   package.json

Inside src/ create a file testrx.js, and write the following code −

testrx.js

import { of } from 'rxjs;
import { map } from 'rxjs/operators';

map(x => x * x)(of(1, 2, 3)).subscribe((v) => console.log(`Output is: ${v}`));

When we go to execute the above code in command prompt, using command − node testrx.js, it will display error for import, as nodejs does not know what to do with import.

To make import work with nodejs, we need to install ES6 modules package using npm as shown below −

E:
xjsprojsrc>npm install --save-dev esm
npm WARN rxjsproj@1.0.0 No description
npm WARN rxjsproj@1.0.0 No repository field.

+ esm@3.2.25
added 1 package from 1 contributor and audited 3 packages in 9.32s
found 0 vulnerabilities

Once the package is installed, we can now execute testrx.js file as shown below −

E:
xjsprojsrc>node -r esm testrx.js
Output is: 1
Output is: 4
Output is: 9

We can see the output now, that shows RxJS is installed and ready to use. The above method will help us test RxJS in the command line. In case, you want to test RxJS in the browser, we would need some additional packages.

Testing RxJS in Browser

Install following packages inside rxjsproj/ folder −

npm install --save-dev babel-loader @babel/core @babel/preset-env webpack webpack-cli webpack-dev-server
E:
xjsproj>npm install --save-dev babel-loader 
@babel/core @babel/preset-env webpack webpack-cli webpack-dev-server

npm WARN rxjsproj@1.0.0 No description
npm WARN rxjsproj@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9
(node_modulessevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@
1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ webpack-dev-server@3.8.0
+ babel-loader@8.0.6
+ @babel/preset-env@7.6.0
+ @babel/core@7.6.0
+ webpack-cli@3.3.8
+ webpack@4.39.3
added 675 packages from 373 contributors and audited 10225 packages in 255.567s
found 0 vulnerabilities

To start the server to execute our Html file, we will use webpack-server. The command "publish" in package.json will help us start as well as pack all the js files using webpack . The packed js files which are our final js file to be used is saved at the path /dev folder.

To use webpack, we need to run npm run publish command and the command is added in package.json as shown below −

Package.json

{
   "name": "rxjsproj",
   "version": "1.0.0",
   "description": "",
   "main": "index.js",
   "scripts": {
      "publish":"webpack && webpack-dev-server --output-public=/dev/",
      "test": "echo "Error: no test specified" && exit 1"
   },
   "author": "",
   "license": "ISC",
   "devDependencies": {
      "@babel/core": "^7.6.0",
      "@babel/preset-env": "^7.6.0",
      "babel-loader": "^8.0.6",
      "esm": "^3.2.25",
      "rxjs": "^6.5.3",
      "webpack": "^4.39.3",
      "webpack-cli": "^3.3.8",
      "webpack-dev-server": "^3.8.0"
   }
}

To work with webpack we must first create a file called webpack.config.js that has the configuration details for webpack to work.

The details in the file are as follows −

var path = require('path');

module.exports = {
   entry: {
      app: './src/testrx.js'
   },
   output: {
      path: path.resolve(__dirname, 'dev'),
      filename: 'main_bundle.js'
   },
   mode:'development',
   module: {
      rules: [
         {
            test:/.(js)$/,
            include: path.resolve(__dirname, 'src'),
            loader: 'babel-loader',
            query: {
               presets: ['@babel/preset-env']
            }
         }
      ]
   }
};

The structure of the file is as shown above. It starts with a path that gives the current path details.

var path = require('path'); //gives the current path

Next is module.exports object which has properties entry, output, and module. Entry is the start point. Here, we need to give the start js file we want to compile.

entry: {
   app: './src/testrx.js'
},

path.resolve(_dirname, ‘src/testrx.js’) -- will look for src folder in the directory and testrx.js in that folder.

Output

output: {
   path: path.resolve(__dirname, 'dev'),
   filename: 'main_bundle.js'
},

The output is an object with path and filename details.path will hold the folder in which the compiled file will be kept and the filename will tell the name of the final file to be used in your .html file.

Module

module: {
   rules: [
      {
         test:/.(js)$/,
         include: path.resolve(__dirname, 'src'),
         loader: 'babel-loader',
         query: {
            presets: ['@babel/preset-env']
         }
      }
   ]
}

Module is object with rules details which has properties i.e. test, include, loader, query. The test will hold details of all the js file ending with .js and .jsx. It has the pattern which will look for .js at the end in the entry point given.

Include tells the folder to be used for looking at the files.

The loader uses babel-loader for compiling code.

The query has property presets which is an array with value '@babel/preset-env’. It will transpile the code as per the ES environment you need.

The final folder structure will be as follows −

rxjsproj/
   node_modules/
   src/
      testrx.js
   index.html
   package.json
   webpack.config.js

Run Command

npm run publish will create dev/ folder with main_bundle.js file in it. The server will be started and you can test your index.html in the browser as shown below.

Run Command

Open the browser and hit the url − http://localhost:8080/

Main Bundle

The output is shown in the console.

RxJS - Latest Updates

We are using RxJS version 6 in this tutorial. RxJS is commonly used to deal with reactive programming and used more often with Angular, ReactJS. Angular 6 loads rxjs6 by default.

RxJS version 5 was handled differently in comparison to version 6. The code will break in case you update your RxJS 5 to 6. In this chapter, we are going to see the difference in ways of handling the version update.

In case you are updating RxJS to 6 and don't want to make the code changes, you can do that too, and will have to install the following package.

npm install --save-dev rxjs-compact

This package will take care of providing backward compatibility and old code will work fine with RxJS version 6. If you want to make the code changes that works fine with RxJS 6, here are the changes that needs to be done.

The packages for operators, observables, subject were restructured and hence, the major changes go in for imports and they are explained below.

Imports for operators

As per version 5, for operators the following import statements should be included −

import 'rxjs/add/operator/mapTo'
import 'rxjs/add/operator/take'
import 'rxjs/add/operator/tap'
import 'rxjs/add/operator/map'

In RxJS version 6 the imports will be as follows −

import {mapTo, take, tap, map} from "rxjs/operators"

Import of Methods to create Observables

As per version 5, while working with Observables, the following import methods should be included −

import "rxjs/add/observable/from";
import "rxjs/add/observable/of";
import "rxjs/add/observable/fromEvent";
import "rxjs/add/observable/interval";

In RxJS version 6 the imports will be as follows −

import {from, of, fromEvent, interval} from 'rxjs';

Import of Observables

In RxJS version 5, while working with Observables, the following import statements should be included −

import { Observable } from 'rxjs/Observable'

In RxJS version 6, the imports will be as follows −

import { Observable } from 'rxjs'

Import of Subject

In RxJS version 5, subject should be included as follows −

import { Subject} from 'rxjs/Subject'

In RxJS version 6, the imports will be as follows −

import { Subject } from 'rxjs'

How to use operators in RxJS 6?

pipe() method is available on the observable created. It is added to RxJS from version 5.5. Using pipe() now you can work on multiple operators together in sequential order. This is how the operators were used in RxJS version 5.

Example

import "rxjs/add/observable/from";
import 'rxjs/add/operator/max'

let list1 = [1, 6, 15, 10, 58, 2, 40];
from(list1).max((a,b)=>a-b).subscribe(x => console.log("The Max value is "+x));

From RxJS version 5.5 onwards, we have to use pipe() to execute the operator −

Example

import { from } from 'rxjs';
import { max } from 'rxjs/operators';

from(list1).pipe(max((a,b)=>a-b)).subscribe(x => console.log(
   "The Max value is "+x)
);

Operators Renamed

During restructuring of the packages some of the operators were renamed as they were conflicting or matching with javascript keywords. The list is as shown below −

Operator Renamed to
do() tap()
catch() catchError()
switch() switchAll()
finally() finalize()
throw() throwError()

RxJS - Observables

An observable is a function that creates an observer and attaches it to the source where values are expected from, for example, clicks, mouse events from a dom element or an Http request, etc.

Observer is an object with callback functions, that will get called when there is interaction to the Observable, i.e., the source has interacted for an example button click, Http request, etc.

We are going to discuss following topics in this chapter −

  • Create Observable
  • Subscribe Observable
  • Execute Observable

Create Observable

The observable can be created using observable constructor and also using observable create method and by passing subscribe function as an argument to it as shown below −

testrx.js

import { Observable } from 'rxjs';

var observable = new Observable(
   function subscribe(subscriber) {
      subscriber.next("My First Observable")
   }
);

We have created an observable and added a message “My First Observable” using subscriber.next method available inside Observable.

We can also create Observable using, Observable.create() method as shown below −

testrx.js

import { Observable } from 'rxjs';
var observer = Observable.create(
   function subscribe(subscriber) {
      subscriber.next("My First Observable")
   }
);

Subscribe Observable

You can subscribe to an observable as follows −

testrx.js

import { Observable } from 'rxjs';

var observer = new Observable(
   function subscribe(subscriber) {
      subscriber.next("My First Observable")
   }
);
observer.subscribe(x => console.log(x));

When the observer is subscribed, it will start the execution of the Observable.

This is what we see in the browser console −

Subscribe Observable

Execute Observable

An observable gets executed when it is subscribed. An observer is an object with three methods that are notified,

next() − This method will send values like a number, string, object etc.

complete() − This method will not send any value and indicates the observable as completed.

error() − This method will send the error if any.

Let us create the observable with all three notifications and execute the same.

testrx.js

import { Observable } from 'rxjs';
var observer = new Observable(
   function subscribe(subscriber) {
      try {
         subscriber.next("My First Observable");
         subscriber.next("Testing Observable");
         subscriber.complete();
      } catch(e){
         subscriber.error(e);
      }
   }
);
observer.subscribe(x => console.log(x), (e)=>console.log(e), 
   ()=>console.log("Observable is complete"));

In the above code, we have added, next, complete and error method.

try{
   subscriber.next("My First Observable");
   subscriber.next("Testing Observable");
   subscriber.complete();
} catch(e){
   subscriber.error(e);
}

To execute next, complete and error, we have to call the subscribe method as shown below −

observer.subscribe(x => console.log(x), (e)=>console.log(e), 
   ()=>console.log("Observable is complete"));

The error method will be invoked only if there is an error.

This is the output seen in the browser −

Execute Observable

RxJS - Operators

Operators are an important part of RxJS. An operator is a pure function that takes in observable as input and the output is also an observable.

Working with Operators

An operator is a pure function which takes in observable as input and the output is also an observable.

To work with operators we need a pipe() method.

Example of using pipe()

let obs = of(1,2,3); // an observable
obs.pipe(
   operator1(),
   operator2(),
   operator3(),
   operator3(),
)

In above example we have created a observable using of() method that takes in values 1, 2 and 3. Now on this observable you can perform different operation using any numbers of operators using pipe() method as shown above. The execution of operators will go on sequentially on the observable given.

Below is a working example −

import { of } from 'rxjs';
import { map, reduce, filter } from 'rxjs/operators';

let test1 = of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
let case1 = test1.pipe(
   filter(x => x % 2 === 0),
   reduce((acc, one) => acc + one, 0)
)
case1.subscribe(x => console.log(x));

Output

30

In above example, we have used filter operator that, filters the even numbers and, next we have used reduce() operator that will add the even values and give the result when subscribed.

Here is a list of Observables that we are going to discuss.

  • Creation
  • Mathematical
  • Join
  • Transformation
  • Filtering
  • Utility
  • Conditional
  • Multicasting
  • Error handling

Creation Operators

Following are the operators we are going to discuss in Creation operator category −

Sr.No Operator & Description
1 ajax

This operator will make an ajax request for the given URL.

2 from

This operator will create an observable from an array, an array-like object, a promise, an iterable object, or an observable-like object.

3 fromEvent

This operator will give output as an observable that is to be used on elements that emit an event for example buttons, clicks, etc.

4 fromEventPattern

This operator will create an observable from the input function that is used to register event handlers.

5 interval

This operator will create an Observable for every time for the time given..

6 of

This operator will take in the arguments passed and convert them to observable.

7 range

This operator will create an Observable that will give you a sequence of numbers based on the range provided.

8 throwError

This operator will create an observable that will notify an error.

9 timer

This operator will create an observable that will emit the value after the timeout and the value will keep increasing after each call.

10 iif

This operator will decide which Observable will be subscribed.

Mathematical Operators

The following are the operators we are going to discuss in the Mathematical operator category −

Sr.No Operator & Description
1 Count

The count() operator takes in an Observable with values and converts it into an Observable that will give a single value

2 Max

Max method will take in an observable with all values and return an observable with the max value

3 Min

Min method will take in an observable with all values and return an observable with the min value.

4 Reduce

In reduce operator, accumulator function is used on the input observable, and the accumulator function will return the accumulated value in the form of an observable, with an optional seed value passed to the accumulator function.

The reduce() function will take in 2 arguments, one accumulator function, and second the seed value.

Join Operators

The following are the operators we are going to discuss in the Join operator category.

Sr.No Operator & Description
1 concat

This operator will sequentially emit the Observable given as input and proceed to the next one.

2 forkJoin

This operator will be taken in an array or dict object as an input and will wait for the observable to complete and return the last values emitted from the given observable.

3 merge

This operator will take in the input observable and will emit all the values from the observable and emit one single output observable.

4 race

It will give back an observable that will be a mirror copy of the first source observable.

Transformation Operators

The following are the operators we are going to discuss in the Transformation operator category.

Sr.No Operator & Description
1 buffer

The buffer operates on an observable and takes in argument as an observable. It will start buffering the values emitted on its original observable in an array and will emit the same when the observable taken as argument, emits. Once the observable taken as arguments emits, the buffer is reset and starts buffering again on original till the input observable emits and the same scenario repeats.

2 bufferCount

In the case of buffercount() operator, it will collect the values from the observable on which it is called and emit the same when the buffer size given to buffercount matches.

3 bufferTime

This is similar to bufferCount, so here, it will collect the values from the observable on which it is called and emit the bufferTimeSpan is done. It takes in 1 argument i.e. bufferTimeSpan.

4 bufferToggle

In the case of bufferToggle() it takes 2 arguments, openings and closingSelector. The opening arguments are subscribable or a promise to start the buffer and the second argument closingSelector is again subscribable or promise an indicator to close the buffer and emit the values collected.

5 bufferWhen

This operator will give the values in the array form, it takes in one argument as a function that will decide when to close, emit and reset the buffer.

6 expand

The expand operator takes in a function as an argument which is applied on the source observable recursively and also on the output observable. The final value is an observable.

7 groupBy

In groupBy operator, the output is grouped based on a specific condition and these group items are emitted as GroupedObservable.

8 map

In the case of map operator, a project function is applied on each value on the source Observable and the same output is emitted as an Observable.

9 mapTo

A constant value is given as output along with the Observable every time the source Observable emits a value.

10 mergeMap

In the case of mergeMap operator, a project function is applied on each source value and the output of it is merged with the output Observable.

11 switchMap

In the case of switchMap operator, a project function is applied on each source value and the output of it is merged with the output Observable, and the value given is the most recent projected Observable.

12 window

It takes an argument windowboundaries which is an observable and gives back a nested observable whenever the given windowboundaries emits

Filtering Operators

The following are the operators we are going to discuss in the filtering operator category.

Sr.No Operator & Description
1 debounce

A value emitted from the source Observable after a while and the emission is determined by another input given as Observable or promise.

2 debounceTime

It will emit value from the source observable only after the time is complete.

3 distinct

This operator will give all the values from the source observable that are distinct when compared with the previous value.

4 elementAt

This operator will give a single value from the source observable based upon the index given.

5 filter

This operator will filter the values from source Observable based on the predicate function given.

6 first

This operator will give the first value emitted by the source Observable.

7 last

This operator will give the last value emitted by the source Observable.

8 ignoreElements

This operator will ignore all the values from the source Observable and only execute calls to complete or error callback functions.

9 sample

This operator will give the most recent value from the source Observable , and the output will depend upon the argument passed to it emits.

10 skip

This operator will give back an observable that will skip the first occurrence of count items taken as input.

11 throttle

This operator will output as well as ignore values from the source observable for the time determined by the input function taken as an argument and the same process will be repeated.

Utility Operators

The following are the operators we are going to discuss in the utility operator category.

Sr.No Operator & Description
1 tap

This operator will have the output, the same as the source observable, and can be used to log the values to the user from the observable. The main value, error if any or if the task is complete.

2 delay

This operator delays the values emitted from the source Observable based on the timeout given.

3 delayWhen

This operator delays the values emitted from the source Observable based on the timeout from another observable taken as input.

4 observeOn

This operator based on the input scheduler will reemit the notifications from the source Observable.

5 subscribeOn

This operator helps to asynchronous subscribes to the source Observable based on the scheduler taken as input.

6 timeInterval

This operator will return an object which contains current value and the time elapsed between the current and previous value that is calculated using scheduler input taken.

7 timestamp

Returns the timestamp along with the value emitted from source Observable which tells about the time when the value was emitted.

8 timeout

This operator will throw an error if the source Observable does not emit a value after the given timeout.

9 toArray

Accumulates all the source value from the Observable and outputs them as an array when the source completes.

Conditional Operators

The following are the operators we are going to discuss in the conditional operator category.

Sr.No Operator & Description
1 defaultIfEmpty

This operator will return a default value if the source observable is empty.

2 every

It will return an Observable based on the input function satisfies the condition on each of the value on source Observable.

3 find

This will return the observable when the first value of the source Observable satisfies the condition for the predicate function taken as input.

4 findIndex

This operator based on the input scheduler will reemit the notifications from the source Observable.

5 isEmpty

This operator will give the output as true if the input observable goes for complete callback without emitting any values and false if the input observable emits any values.

Multicasting Operators

The following are the operators we are going to discuss in the multicasting operator category..

Sr.No Operator & Description
1 multicast

A multicast operator shares the single subscription created with other subscribers. The params that multicast takes in, is a subject or a factory method that returns a ConnectableObservable that has connect() method. To subscribe, connect() method has to be called.

2 publish

This operator gives back ConnectableObservable and needs to use connect() method to subscribe to the observables.

3 publishBehavior

publishBehaviour make use of BehaviourSubject, and returns ConnectableObservable. The connect() method has to be used to subscribe to the observable created.

4 publishLast

publishBehaviour make use of AsyncSubject, and returns back ConnectableObservable. The connect() method has to be used to subscribe to the observable created.

5 publishReplay

publishReplay make use of behaviour subject wherein it can buffer the values and replay the same to the new subscribers and returns ConnectableObservable. The connect() method has to be used to subscribe to the observable created.

6 share

It is an alias for mutlicast() operator with the only difference is that you don't have to called connect () method manually to start the subscription.

Error Handling Operators

The following are the operators we are going to discuss in error handling operator category.

Sr.No Operator & Description
1 catchError

This operator takes care of catching errors on the source Observable by returning a new Observable or an error.

2 retry

This operator will take care of retrying back on the source Observable if there is error and the retry will be done based on the input count given.

RxJS - Working with Subscription

When the observable is created, to execute the observable we need to subscribe to it.

count() operator

Here, is a simple example of how to subscribe to an observable.

Example 1

import { of } from 'rxjs';
import { count } from 'rxjs/operators';

let all_nums = of(1, 7, 5, 10, 10, 20);
let final_val = all_nums.pipe(count());
final_val.subscribe(x => console.log("The count is "+x));

Output

The count is 6

The subscription has one method called unsubscribe(). A call to unsubscribe() method will remove all the resources used for that observable i.e. the observable will get canceled. Here, is a working example of using unsubscribe() method.

Example 2

import { of } from 'rxjs';
import { count } from 'rxjs/operators';

let all_nums = of(1, 7, 5, 10, 10, 20);
let final_val = all_nums.pipe(count());
let test = final_val.subscribe(x => console.log("The count is "+x));
test.unsubscribe();

The subscription is stored in the variable test. We have used test.unsubscribe() the observable.

Output

The count is 6

RxJS - Working with Subjects

A subject is an observable that can multicast i.e. talk to many observers. Consider a button with an event listener, the function attached to the event using add listener is called every time the user clicks on the button similar functionality goes for subject too.

We are going to discuss the following topics in this chapter −

  • Create a subject
  • What is the Difference between Observable and Subject?
  • Behaviour Subject
  • Replay Subject
  • AsyncSubject

Create a subject

To work with subject, we need to import Subject as shown below −

import { Subject } from 'rxjs';

You can create a subject object as follows −

const subject_test = new Subject();

The object is an observer that has three methods −

  • next(v)
  • error(e)
  • complete()

Subscribe to a Subject

You can create multiple subscription on the subject as shown below −

subject_test.subscribe({
   next: (v) => console.log(`From Subject : ${v}`)
});
subject_test.subscribe({
   next: (v) => console.log(`From Subject: ${v}`)
});

The subscription is registered to the subject object just like addlistener we discussed earlier.

Passing Data to Subject

You can pass data to the subject created using the next() method.

subject_test.next("A");

The data will be passed to all the subscription added on the subject.

Example

Here, is a working example of the subject −

import { Subject } from 'rxjs';

const subject_test = new Subject();

subject_test.subscribe({
   next: (v) => console.log(`From Subject : ${v}`)
});
subject_test.subscribe({
   next: (v) => console.log(`From Subject: ${v}`)
});
subject_test.next("A");
subject_test.next("B");

The subject_test object is created by calling a new Subject(). The subject_test object has reference to next(), error() and complete() methods. The output of the above example is shown below −

Output

Passing Data

We can use complete() method to stop the subject execution as shown below.

Example

import { Subject } from 'rxjs';

const subject_test = new Subject();

subject_test.subscribe({
   next: (v) => console.log(`From Subject : ${v}`)
});
subject_test.subscribe({
   next: (v) => console.log(`From Subject: ${v}`)
});
subject_test.next("A");
subject_test.complete();
subject_test.next("B");

Once we call complete the next method called later is not invoked.

Output

Passing Data Method

Let us now see how to call error () method.

Example

Below is a working example −

import { Subject } from 'rxjs';

const subject_test = new Subject();

subject_test.subscribe({
   error: (e) => console.log(`From Subject : ${e}`)
});
subject_test.subscribe({
   error: (e) => console.log(`From Subject : ${e}`)
});
subject_test.error(new Error("There is an error"));

Output

Passing Data Error

What is the Difference between Observable and Subject?

An observable will talk one to one, to the subscriber. Anytime you subscribe to the observable the execution will start from scratch. Take an Http call made using ajax, and 2 subscribers calling the observable. You will see 2 HttpHttp requests in the browser network tab.

Example

Here is a working example of same −

import { ajax } from 'rxjs/ajax';
import { map } from 'rxjs/operators';

let final_val = ajax('https://jsonplaceholder.typicode.com/users').pipe(map(e => e.response));
let subscriber1 = final_val.subscribe(a => console.log(a));
let subscriber2 = final_val.subscribe(a => console.log(a));

Output

Observable Observable Ex

Now, here the problem is, we want the same data to be shared, but not, at the cost of 2 Http calls. We want to make one Http call and share the data between subscribers.

This will be possible using Subjects. It is an observable that can multicast i.e. talk to many observers. It can share the value between subscribers.

Example

Here is a working example using Subjects −

import { Subject } from 'rxjs';
import { ajax } from 'rxjs/ajax';
import { map } from 'rxjs/operators';

const subject_test = new Subject();

subject_test.subscribe({
   next: (v) => console.log(v)
});
subject_test.subscribe({
   next: (v) => console.log(v)
});

let final_val = ajax('https://jsonplaceholder.typicode.com/users').pipe(map(e => e.response));
let subscriber = final_val.subscribe(subject_test);

Output

Observable possible

Now you can see only one Http call and the same data is shared between the subscribers called.

Observable subscribers

Behaviour Subject

Behaviour subject will give you the latest value when called.

You can create behaviour subject as shown below −

import { BehaviorSubject } from 'rxjs';
const subject = new BehaviorSubject("Testing Behaviour Subject"); 
// initialized the behaviour subject with value:Testing Behaviour Subject

Example

Here is a working example to use Behaviour Subject −

import { BehaviorSubject } from 'rxjs';
const behavior_subject = new BehaviorSubject("Testing Behaviour Subject"); 
// 0 is the initial value

behavior_subject.subscribe({
   next: (v) => console.log(`observerA: ${v}`)
});

behavior_subject.next("Hello");
behavior_subject.subscribe({
   next: (v) => console.log(`observerB: ${v}`)
});
behavior_subject.next("Last call to Behaviour Subject");

Output

Behaviour Subject

Replay Subject

A replaysubject is similar to behaviour subject, wherein, it can buffer the values and replay the same to the new subscribers.

Example

Here is a working example of replay subject −

import { ReplaySubject } from 'rxjs';
const replay_subject = new ReplaySubject(2); 
// buffer 2 values but new subscribers

replay_subject.subscribe({
   next: (v) => console.log(`Testing Replay Subject A: ${v}`)
});

replay_subject.next(1);
replay_subject.next(2);
replay_subject.next(3);
replay_subject.subscribe({
   next: (v) => console.log(`Testing Replay Subject B: ${v}`)
});

replay_subject.next(5);

The buffer value used is 2 on the replay subject. So the last two values will be buffered and used for the new subscribers called.

Output

Replay Subject

AsyncSubject

In the case of AsyncSubject the last value called is passed to the subscriber and it will be done only after complete() method is called.

Example

Here is a working example of the same −

import { AsyncSubject } from 'rxjs';

const async_subject = new AsyncSubject();

async_subject.subscribe({
   next: (v) => console.log(`Testing Async Subject A: ${v}`)
});

async_subject.next(1);
async_subject.next(2);
async_subject.complete();
async_subject.subscribe({
   next: (v) => console.log(`Testing Async Subject B: ${v}`)
});

Here, before complete is called the last value passed to the subject is 2 and the same it given to the subscribers.

Output

Async Subject

RxJS - Working with Scheduler

A scheduler controls the execution of when the subscription has to start and notified.

To make use of scheduler we need the following −

import { Observable, asyncScheduler } from 'rxjs';
import { observeOn } from 'rxjs/operators';

Here is a working example, wherein, we will use the scheduler that will decide the execution.

Example

import { Observable, asyncScheduler } from 'rxjs';
import { observeOn } from 'rxjs/operators';

var observable = new Observable(function subscribe(subscriber) {
   subscriber.next("My First Observable");
   subscriber.next("Testing Observable");
   subscriber.complete();
}).pipe(
   observeOn(asyncScheduler)
);
console.log("Observable Created");
observable.subscribe(
   x => console.log(x),
   (e)=>console.log(e),
   ()=>console.log("Observable is complete")
);

console.log('Observable Subscribed');

Output

Scheduler

Without scheduler the output would have been as shown below −

Scheduler Controls

Working with RxJS & Angular

In this chapter, we will see how to use RxJs with Angular. We will not get into the installation process for Angular here, to know about Angular Installation refer this link −https://www.tutorialspoint.com/angular7/angular7_environment_setup.htm

We will directly work on an example, where will use Ajax from RxJS to load data.

Example

app.component.ts

import { Component } from '@angular/core';
import { environment } from './../environments/environment';
import { ajax } from 'rxjs/ajax';
import { map } from 'rxjs/operators'

@Component({
   selector: 'app-root',
   templateUrl: './app.component.html',
   styleUrls: ['./app.component.css']
})
export class AppComponent {
   title = '';
   data;
   constructor() {
      this.data = "";
      this.title = "Using RxJs with Angular";
      let a = this.getData();
   }
   getData() {
      const response =
      ajax('https://jsonplaceholder.typicode.com/users')
         .pipe(map(e => e.response));
      response.subscribe(res => {
         console.log(res);
         this.data = res;
      });
   }
}

app.component.html

<div>
   <h3>{{title}}</h3>
   <ul *ngFor="let i of data">
      <li>{{i.id}}: {{i.name}}</li>
   </ul>
</div>

<router-outlet></router-outlet>

We have used ajax from RxJS that will load data from this url − https://jsonplaceholder.typicode.com/users.

When you compile the display is as shown below −

RxJs with Angular

Working with RxJS & ReactJS

In this chapter, we will see how to use RxJs with ReactJS. We will not get into the installation process for Reactjs here, to know about ReactJS Installation refer this link: https://www.yoursite.com/reactjs/reactjs_environment_setup.htm

Example

We will directly work on an example below, where will use Ajax from RxJS to load data.

index.js

import React, { Component } from "react";
import ReactDOM from "react-dom";
import { ajax } from 'rxjs/ajax';
import { map } from 'rxjs/operators';
class App extends Component {
   constructor() {
      super();
      this.state = { data: [] };
   }
   componentDidMount() {
      const response = ajax('https://jsonplaceholder.typicode.com/users').pipe(map(e => e.response));
      response.subscribe(res => {
         this.setState({ data: res });
      });
   }
   render() {
      return (
         <div>
            <h3>Using RxJS with ReactJS</h3>
            <ul>
               {this.state.data.map(el => (
                  <li>
                     {el.id}: {el.name}
                  </li>
               ))}
            </ul>
         </div>
      );
   }
}
ReactDOM.render(<App />, document.getElementById("root"));

index.html

<!DOCTYPE html>
<html>
   <head>
      <meta charset = "UTF-8" />
      <title>ReactJS Demo</title>
   <head>
   <body>
      <div id = "root"></div>
   </body>
</html>

We have used ajax from RxJS that will load data from this Url − https://jsonplaceholder.typicode.com/users.

When you compile, the display is as shown below −

RxJs with ReactJS

ReactJS Tutorial

posted on June 7, 2021

tags:

ReactJS is JavaScript library used for building reusable UI components. According to React official documentation, following is the definition −

React is a library for building composable user interfaces. It encourages the creation of reusable UI components, which present data that changes over time. Lots of people use React as the V in MVC. React abstracts away the DOM from you, offering a simpler programming model and better performance. React can also render on the server using Node, and it can power native apps using React Native. React implements one-way reactive data flow, which reduces the boilerplate and is easier to reason about than traditional data binding.

React Features

  • JSX − JSX is JavaScript syntax extension. It isn't necessary to use JSX in React development, but it is recommended.

  • Components − React is all about components. You need to think of everything as a component. This will help you maintain the code when working on larger scale projects.

  • Unidirectional data flow and Flux − React implements one-way data flow which makes it easy to reason about your app. Flux is a pattern that helps keeping your data unidirectional.

  • License − React is licensed under the Facebook Inc. Documentation is licensed under CC BY 4.0.

React Advantages

  • Uses virtual DOM which is a JavaScript object. This will improve apps performance, since JavaScript virtual DOM is faster than the regular DOM.

  • Can be used on client and server side as well as with other frameworks.

  • Component and data patterns improve readability, which helps to maintain larger apps.

React Limitations

  • Covers only the view layer of the app, hence you still need to choose other technologies to get a complete tooling set for development.

  • Uses inline templating and JSX, which might seem awkward to some developers.

ReactJS - Environment Setup

In this chapter, we will show you how to set up an environment for successful React development. Notice that there are many steps involved but this will help speed up the development process later. We will need NodeJS, so if you don't have it installed, check the link from the following table.

Sr.No. Software & Description
1

NodeJS and NPM

NodeJS is the platform needed for the ReactJS development. Checkout our NodeJS Environment Setup.

After successfully installing NodeJS, we can start installing React upon it using npm. You can install ReactJS in two ways

  • Using webpack and babel.

  • Using the create-react-app command.

Installing ReactJS using webpack and babel

Webpack is a module bundler (manages and loads independent modules). It takes dependent modules and compiles them to a single (file) bundle. You can use this bundle while developing apps using command line or, by configuring it using webpack.config file.

Babel is a JavaScript compiler and transpiler. It is used to convert one source code to other. Using this you will be able to use the new ES6 features in your code where, babel converts it into plain old ES5 which can be run on all browsers.

Step 1 - Create the Root Folder

Create a folder with name reactApp on the desktop to install all the required files, using the mkdir command.

C:UsersusernameDesktop>mkdir reactApp
C:UsersusernameDesktop>cd reactApp

To create any module, it is required to generate the package.json file. Therefore, after Creating the folder, we need to create a package.json file. To do so you need to run the npm init command from the command prompt.

C:UsersusernameDesktop
eactApp>npm init

This command asks information about the module such as packagename, description, author etc. you can skip these using the –y option.

C:UsersusernameDesktop
eactApp>npm init -y
Wrote to C:
eactApppackage.json:
{
   "name": "reactApp",
   "version": "1.0.0",
   "description": "",
   "main": "index.js",
   "scripts": {
      "test": "echo "Error: no test specified" && exit 1"
   },
   "keywords": [],
   "author": "",
   "license": "ISC"
}

Step 2 - install React and react dom

Since our main task is to install ReactJS, install it, and its dom packages, using install react and react-dom commands of npm respectively. You can add the packages we install, to package.json file using the --save option.

C:UsersTutorialspointDesktop
eactApp>npm install react --save
C:UsersyoursiteDesktop
eactApp>npm install react-dom --save

Or, you can install all of them in single command as −

C:UsersusernameDesktop
eactApp>npm install react react-dom --save

Step 3 - Install webpack

Since we are using webpack to generate bundler install webpack, webpack-dev-server and webpack-cli.

C:UsersusernameDesktop
eactApp>npm install webpack --save
C:UsersusernameDesktop
eactApp>npm install webpack-dev-server --save
C:UsersusernameDesktop
eactApp>npm install webpack-cli --save

Or, you can install all of them in single command as −

C:UsersusernameDesktop
eactApp>npm install webpack webpack-dev-server webpack-cli --save

Step 4 - Install babel

Install babel, and its plugins babel-core, babel-loader, babel-preset-env, babel-preset-react and, html-webpack-plugin

C:UsersusernameDesktop
eactApp>npm install babel-core --save-dev
C:UsersusernameDesktop
eactApp>npm install babel-loader --save-dev
C:UsersusernameDesktop
eactApp>npm install babel-preset-env --save-dev
C:UsersusernameDesktop
eactApp>npm install babel-preset-react --save-dev
C:UsersusernameDesktop
eactApp>npm install html-webpack-plugin --save-dev

Or, you can install all of them in single command as −

C:UsersusernameDesktop
eactApp>npm install babel-core babel-loader babel-preset-env 
   babel-preset-react html-webpack-plugin --save-dev

Step 5 - Create the Files

To complete the installation, we need to create certain files namely, index.html, App.js, main.js, webpack.config.js and, .babelrc. You can create these files manually or, using command prompt.

C:UsersusernameDesktop
eactApp>type nul > index.html
C:UsersusernameDesktop
eactApp>type nul > App.js
C:UsersusernameDesktop
eactApp>type nul > main.js
C:UsersusernameDesktop
eactApp>type nul > webpack.config.js
C:UsersusernameDesktop
eactApp>type nul > .babelrc

Step 6 - Set Compiler, Server and Loaders

Open webpack-config.js file and add the following code. We are setting webpack entry point to be main.js. Output path is the place where bundled app will be served. We are also setting the development server to 8001 port. You can choose any port you want.

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
   entry: './main.js',
   output: {
      path: path.join(__dirname, '/bundle'),
      filename: 'index_bundle.js'
   },
   devServer: {
      inline: true,
      port: 8001
   },
   module: {
      rules: [
         {
            test: /.jsx?$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            query: {
               presets: ['es2015', 'react']
            }
         }
      ]
   },
   plugins:[
      new HtmlWebpackPlugin({
         template: './index.html'
      })
   ]
}

Open the package.json and delete "test" "echo "Error: no test specified" && exit 1" inside "scripts" object. We are deleting this line since we will not do any testing in this tutorial. Let's add the start and build commands instead.

"start": "webpack-dev-server --mode development --open --hot",
"build": "webpack --mode production"

Step 7 - index.html

This is just regular HTML. We are setting div id = "app" as a root element for our app and adding index_bundle.js script, which is our bundled app file.

<!DOCTYPE html>
<html lang = "en">
   <head>
      <meta charset = "UTF-8">
      <title>React App</title>
   </head>
   <body>
      <div id = "app"></div>
      <script src = 'index_bundle.js'></script>
   </body>
</html>

Step 8 − App.jsx and main.js

This is the first React component. We will explain React components in depth in a subsequent chapter. This component will render Hello World.

App.js

import React, { Component } from 'react';
class App extends Component{
   render(){
      return(
         <div>
            <h1>Hello World</h1>
         </div>
      );
   }
}
export default App;

We need to import this component and render it to our root App element, so we can see it in the browser.

main.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';

ReactDOM.render(<App />, document.getElementById('app'));

Note − Whenever you want to use something, you need to import it first. If you want to make the component usable in other parts of the app, you need to export it after creation and import it in the file where you want to use it.

Create a file with name .babelrc and copy the following content to it.

{
   "presets":["env", "react"]
}

Step 9 - Running the Server

The setup is complete and we can start the server by running the following command.

C:UsersusernameDesktop
eactApp>npm start

It will show the port we need to open in the browser. In our case, it is http://localhost:8001/. After we open it, we will see the following output.

Running the Server

Step 10 - Generating the bundle

Finally, to generate the bundle you need to run the build command in the command prompt as −

C:UsersyoursiteDesktop
eactApp>npm run build

This will generate the bundle in the current folder as shown below.

Generating the bundle

Using the create-react-app command

Instead of using webpack and babel you can install ReactJS more simply by installing create-react-app.

Step 1 - install create-react-app

Browse through the desktop and install the Create React App using command prompt as shown below −

C:Usersyoursite>cd C:UsersyoursiteDesktop
C:UsersyoursiteDesktop>npx create-react-app my-app

This will create a folder named my-app on the desktop and installs all the required files in it.

Step 2 - Delete all the source files

Browse through the src folder in the generated my-app folder and remove all the files in it as shown below −

C:UsersyoursiteDesktop>cd my-app/src
C:UsersyoursiteDesktopmy-appsrc>del *
C:UsersyoursiteDesktopmy-appsrc*, Are you sure (Y/N)? y

Step 3 - Add files

Add files with names index.css and index.js in the src folder as −

C:UsersyoursiteDesktopmy-appsrc>type nul > index.css
C:UsersyoursiteDesktopmy-appsrc>type nul > index.js

In the index.js file add the following code

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

Step 4 - Run the project

Finally, run the project using the start command.

npm start

Run the Project

ReactJS - JSX

React uses JSX for templating instead of regular JavaScript. It is not necessary to use it, however, following are some pros that come with it.

  • It is faster because it performs optimization while compiling code to JavaScript.

  • It is also type-safe and most of the errors can be caught during compilation.

  • It makes it easier and faster to write templates, if you are familiar with HTML.

Using JSX

JSX looks like a regular HTML in most cases. We already used it in the Environment Setup chapter. Look at the code from App.jsx where we are returning div.

App.jsx

import React from 'react';

class App extends React.Component {
   render() {
      return (
         <div>
            Hello World!!!
         </div>
      );
   }
}
export default App;

Even though it's similar to HTML, there are a couple of things we need to keep in mind when working with JSX.

Nested Elements

If we want to return more elements, we need to wrap it with one container element. Notice how we are using div as a wrapper for h1, h2 and p elements.

App.jsx

import React from 'react';

class App extends React.Component {
   render() {
      return (
         <div>
            <h1>Header</h1>
            <h2>Content</h2>
            <p>This is the content!!!</p>
         </div>
      );
   }
}
export default App;

React JSX Wrapper

Attributes

We can use our own custom attributes in addition to regular HTML properties and attributes. When we want to add custom attribute, we need to use data- prefix. In the following example, we added data-myattribute as an attribute of p element.

import React from 'react';

class App extends React.Component {
   render() {
      return (
         <div>
            <h1>Header</h1>
            <h2>Content</h2>
            <p data-myattribute = "somevalue">This is the content!!!</p>
         </div>
      );
   }
}
export default App;

JavaScript Expressions

JavaScript expressions can be used inside of JSX. We just need to wrap it with curly brackets {}. The following example will render 2.

import React from 'react';

class App extends React.Component {
   render() {
      return (
         <div>
            <h1>{1+1}</h1>
         </div>
      );
   }
}
export default App;

React JSX Inline Javascript

We cannot use if else statements inside JSX, instead we can use conditional (ternary) expressions. In the following example, variable i equals to 1 so the browser will render true, If we change it to some other value, it will render false.

import React from 'react';

class App extends React.Component {
   render() {
      var i = 1;
      return (
         <div>
            <h1>{i == 1 ? 'True!' : 'False'}</h1>
         </div>
      );
   }
}
export default App;

React JSX Ternary Expression

Styling

React recommends using inline styles. When we want to set inline styles, we need to use camelCase syntax. React will also automatically append px after the number value on specific elements. The following example shows how to add myStyle inline to h1 element.

import React from 'react';

class App extends React.Component {
   render() {
      var myStyle = {
         fontSize: 100,
         color: '#FF0000'
      }
      return (
         <div>
            <h1 style = {myStyle}>Header</h1>
         </div>
      );
   }
}
export default App;

React JSX Inline Style

Comments

When writing comments, we need to put curly brackets {} when we want to write comment within children section of a tag. It is a good practice to always use {} when writing comments, since we want to be consistent when writing the app.

import React from 'react';

class App extends React.Component {
   render() {
      return (
         <div>
            <h1>Header</h1>
            {//End of the line Comment...}
            {/*Multi line comment...*/}
         </div>
      );
   }
}
export default App;

Naming Convention

HTML tags always use lowercase tag names, while React components start with Uppercase.

Note − You should use className and htmlFor as XML attribute names instead of class and for.

This is explained on React official page as −

Since JSX is JavaScript, identifiers such as class and for are discouraged as XML attribute names. Instead, React DOM components expect DOM property names such as className and htmlFor, respectively.

ReactJS - Components

In this chapter, we will learn how to combine components to make the app easier to maintain. This approach allows to update and change your components without affecting the rest of the page.

Stateless Example

Our first component in the following example is App. This component is owner of Header and Content. We are creating Header and Content separately and just adding it inside JSX tree in our App component. Only App component needs to be exported.

App.jsx

import React from 'react';

class App extends React.Component {
   render() {
      return (
         <div>
            <Header/>
            <Content/>
         </div>
      );
   }
}
class Header extends React.Component {
   render() {
      return (
         <div>
            <h1>Header</h1>
         </div>
      );
   }
}
class Content extends React.Component {
   render() {
      return (
         <div>
            <h2>Content</h2>
            <p>The content text!!!</p>
         </div