Angular 2 TV Shopping Cart for Affiliate & MLM Marketing

0
47

Introduction

This is the Anguar 2 version of my AngularJS Shopping Cart posted on CodeProject at:

https://www.codeproject.com/Articles/881354/Affiliate-Marketing-Shopping-Cart-in-AngularJS-Res

Many people would like to sell products online but they don’t have any prodcts to sell. And, many people would like to have other people sell the products they have but don’t know how to find those people.  This Angular 2 Shopping Cart with Video for MLM & Affiliate Marketing does both.  You can give this cart to distributors filled with your products to put on their websites and it will pass the orders to you from any merchant account provider like PayApal with the Distributor ID of the distributor that the order came from so you can pay them commissions. In addition, you can also give distributors a link with their Distributor ID and those orders with the passed in Distributor ID will pass into PayPal or any designated merchant provider.

The Shopping Cart in thDownload sourceis project includes the ability to play videos from servers all over the world. The reason for this is that pictures in shopping carts in today’s world are not feective in delivery the benefits of why somebody should buy a product. A video is a TV commercial that studies have shown is thousands of times more effective in generating sales. For example, teh YOUKU server in China is now the largest television network in teh world and you can post your videos (TV commercials) for free on the YOUKU server and play them in this Shopping Cart in stead of a boring picture of a product.

There are a lot of people who are not computer or Internet savy but who need a simple shopping cart that doesn’t require a database or a programmer to install it. I recall a customer calling me up once for tech support for one of my software programs and telling me “Your software doesn’t work!” I asked what was the problem and he stated that he was stepping on the “foot pedal” and nothing was happening. It turned out that he had put the mouse on the floor and thought you had to pump it with your foot. Needles to say it was a challenge to help him. 

To start with I wanted to include a Pinterest Style Layout so I decided to use a common one that I have seen used often in shopping carts, namely, Codrops famous ViewModeSwitch, that you can find at: https://github.com/codrops/ViewModeSwitch.  ViewModeSwitch is a CSS Pinterest Style Layout that is used n many commercial shopping and it works well with AngularJS with minimal changes.

Angular 2 TV Shopping Cart Features

Here are some of the practical features I included:

  • Written with Angular 2 CLI and Typescript.
  • Ability to GET PAID on Your Commissions and to Pay Commissions.  
  • Reading Config & Products Data BEFORE App Startup in Angular 2 Using APP_INITIALIZER
  • Added Easily Customized Shipping and Handling.
  • Expanded PayPal features Including Notify and Cancel Pages.
  • Must Include Bootstrap 3 without adding ui.bootstrap
  • Must be responsive so it will display and scroll perfectly on any mobile device.
    See example of mobile app using this cart at: www.SerGioApps.com
  • Must have a Cool-Looking, Responsive Bootstrap Menu. 
  • Allow Multiple Stores in our cart.
  • Must read the products and their descriptions from an internal JSON text file.
  • Must read the products and their descriptions from an external JSON text file using JSONP.
  • Must be able to play a Video (TV Commercial) about a product in addition to a picture of the product from hundreds of tube servers around the world. Must play videos posted on the YOUKU server in China which is now the largest television network in the world.
  • Must at least include merchant gateways for PayPal, Google Wallet, and Stripe.
  • Must be extensible so that adding new features like payment methods is easy.
  • Must allow FREE products that can’t be added to the cart using a faux parameter
  • Must handle Google Analytics using Angular 2.
  • Must be able to include links to thrird-party websites like Google Play, etc.
  • Must have a directory structure that allows it to be “dropped” at the root level onto any existing website.
  • Must display selected text as HTML so it attracts the potential customer visually.
  • Must be able to display products in a Pinterest Style Layout or a Listview Layout
  • Must include Slide Button Pagination to control number of products displayed per page
  • Must include Filter & Sort Options
  • Must be able to create Distributor Links for non-Angular sites for Distributor Commissions

Let’s get started to building this Angular2 Mobile App by downloading Node.js which includes npm at https://nodejs.org/en/

At this point if you tried using npm it will most likely give you the dreaded and now famous error:

npm ERR! Windows_NT 6.1.7601  

There are numberous working fixes for this error if you are behind a proxy but if you are’n’t behind a proxy then trying to fix this error can make you crazy. Run the the commands below in a CMD window launched as ADMINISTRATOR:

npm config delete http-proxy
npm config delete https-proxy
npm config delete proxy -g
npm config delete http-proxy -g


npm config set registry "http://registry.npmjs.org"
npm config set strict-ssl false

Let’s Use Angular 2 CLI

We should start by understanding Webpack, System.js and angular-cli. System.js was heavily used in the beginning when Angular 2 was being built. Webpack evolved next and finally, the defacto standard now, Angular CLI evolved as a sort of wrapper for Webpack and to help scaffold new projects and create components. easily. Installing angular-cli which will also install Angular’s “ng” command globally on your system: Directions for installing angular-cli are at: 

https://github.com/angular/angular-cli#updating-angular-cli

npm uninstall -g angular-cli
npm uninstall --save-dev angular-cli
npm uninstall -g @angular/cli
npm cache clean
npm install -g @angular/cli@latest

To verify whether your installation
completed successfully, you can run:

ng version

@angular/cli: 1.0.0-beta.32.3
node: 7.4.0
os: win32 x64

Let’s Create Our Angular 2 Shopping Cart

Now that you have angular-cli installed, you can generate our Angular2 Shopping Cart.  Create a directory for your Angular 2 projects. On my computer I have a directory called “Angular2.” The name of this directory can be anything you want to call it. From inside that directory using the CMD prompt in administrator mode create your “cart-app” as follows:


<span style="color: #990000">C:\Angular2></span>ng new cart-app --routing--style=scss


c:\Angular2>cd cart-app

Underscore is a JavaScript library that provides a lot of useful functional programming helpers without extending any built-in objects. to install it we simply run the following command.



C:\Angular2\cart-app>npm install underscore --save 

C:\Angular2\cart-app>npm install @types/underscore --save-dev 

import * as _ from 'underscore';

Installing & Using Visual Studio Code IDE

I used Microspoft’s Visual Studio Code IDE which you can easily download and install from:  http://code.visualstudio.com/

Open Visual Studio Code and select the project folder “first-app” and open the Integrated Terminal Window as shown below. In the Integrated Terminal Window in Visual Studio Code run the command below which will create your “dist” directory for your finished project.

Then run the default app installed by Angular2-CLI as follows:

C:\Angular2>cart-app>ng serve

This will start our Node.js server running on port 4200 so if you open your Chrome Web Browser to http://localhost:4200 you will see the application running. This will run the default Angular 2 app that comes with Angular 2 CLI. 

What Can Go Wrong When You Run The App?

Many users will get the error:

Module build failed: TypeError: Cannot read property 'newLine' of undefined

When you get this error it is typically caused by either an incorrect version of Angular – CLI. One fix that works is to run:

npm uninstall-g @angular/cli
npm clean cache
npm install Last-g @angular/cli @
then remove the local node_modules folder and run:
install npm–Save-dev @angular/cli @ Last
npm install

You must stay current with the latest changes at: 
https://github.com/angular/angular-cli#updating-angular-cli

Let’s Add the Source Code for Our Angular 2 App

Next we will add the source code for the source code for our shopping cart app to this default project. Download the zipped src.zip file posted above and empty the contents of the zipped “src” folder into the src folder of the project.  And again run the command:

C:\Angular2>cart-app>ng serve

Our Shopping Cart should be running at this point. Next we will coompile our app to run from the “www” folder so you can use it on your website or put it in any mobile device along with Cordova or PhoneGap.

How to Compile Angular 2 Apps Using Ahead-of-Time Compilation (aot)

Why Ahead-of-Time (AOT) compilation Instead of Just-in-Time (JIT) compilation?

  • Much faster rendering, because a pre-compiled version of application downloads.
  • Much fewer asynch requests.
  • AOT ensures that everything is built into a single file (well atleast for your code).
  • Much smaller Angular framework size.
  • AOT will also ensure that your application is “well written” which can be a pain in the butt.

As of Janurary 2017 If you are using angular-cli, AOT compiling is now the default compilation method when running the following command ng build --prod with no code change requirements.

I will jump ahead here to explain how to build your “www” folder for mobile. The BIG SECRET to compiling an Angular 2 App for to run out of a folder isn’t obvious. To build an Amgular 2 App so it will work is setting up the pathways correctly. Look at the index.html from the src folder you added to the project and you will notice that in the index.html file we replaced:

<base href="../" />

with

<script>document.write('<base href="' + document.location + '" />');<script>

When you refresh a page this will dynamically set the base href to your current document.location.

And if you look at app.routing.ts you will see that I added made sure we using Hash Tag Location in app.routing.ts:

@NgModule({ imports: [RouterModule.forRoot(routes, <span style="font-family: 'Courier New' !important; color: #FF0000">{useHash: true}</span>)], exports: [RouterModule] })

Please note that for deployment on a website where refresh needs to work we do set it to true, so instead of:

@NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] })

 Please Note: In a mobile app you would set {useHash: false}. We don’t use has in mobile apps.

Our Angular 2 Shopping Cart is also an Angular 2 Moble App for importing into XCODE (iPhone) or Android Studio. Our default build folder, namely, projectFolder/dist/ Will NOT work for our production version if we also want it to function as a mobile app. To create our production build we need to use some extra commands.

We use the folder name “www” so I can use it as a mobile app as well as a web based app but you can change this to any name after you build it for production and then just paste it into your website.

Let’s create a production build of our Angular 2 Shopping Cart using the following command.





ng build --prod --base-href /$ROOT/Angular2/cart-app/www/

In the pathway above you will notice that I used the folder “Angular2” on my “C” drive and created my “cart-app” folder inside that directory. If you have your project in a different folder then adjust the pathway above accordingly. The contents of the generated “www” folder will go into our “www” folder in Android Stuidio or XCODE to use the Angular 2 Sopping Cart as a Mobile App and all the pathways will actually work. Viola!

Deployment to IIS7 & Other Servers

I still use IIS 7 and on IIS 7 and later versions you MUST be sure to set the MIME type for our json files. Our Angular 2 Shopping Cart uses config.json and products.json which require that the correct MIME Type is set on IIS 7 or any server. By default IIS 7 or any of the IIS are not configure to handle .json extension. So below is a very simple method to do that. You can apply the method on the root of IIS so .json can be handled by every site or virtual folder in the IIS or just to the specific site.

  1. Open IIS Manager
  2. Display properties for IIS Server
  3. Click MIME Types and then add JSON extension:
    • File name extension: .json
    • MIME type: application/json
  4. Go back to the properties for IIS Server
  5. Click on Handler Mappings
    • Add a script map
    • Request path: *.json
    • Executable: C:\WINDOWS\system32\inetsrv\asp.dll
    • Name: JSON

Routing in Our Angular 2 TV Shopping Cart

We have only a few simple views in our app, namely, store, product, checkout, and blank. You can easily add more views like Legal Notices, Terms of service, Refund Policy, Cordova or PhoneGap if you use as a mobile app, etc. BlankComponent is used as a fudge for certain route calls.

const routes: Routes = [
 { path: '', component: StoreComponent },
 { path: 'store', component: StoreComponent },
 { path: 'cart', component: CartComponent },
 { path: 'product/:id', component: ProductComponent },
 { path: 'blank', component: BlankComponent }
];

Reading Data BEFORE App Startup in Angular 2 Using APP_INITIALIZER

We want all of our views to have easy access to our Configuration & Products Data since once loaded this data does NOT change. To accomplish this we add the following in our app.module.ts file as follows.

<span id="ArticleContent22">

import { NgModule } from '@angular/core';
import { APP_INITIALIZER } from '@angular/core';

import { Injectable } from '@angular/core';
import { Http, Jsonp } from "@angular/http";


import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { ConfigService} from './services/config.service';



export function initConfig(config: ConfigService){
 return () => config.load();
}

@NgModule({
 declarations: [
 AppComponent,
 NavbarComponent,
 BlankComponent,
 StoreComponent,
 CartComponent,
 ProductComponent,
 CapitalizePipe,
 UniquePipe,
 OrderByPipe,
 SafeHtmlPipe
 ],
 imports: [
 BrowserModule,
 FormsModule,
 HttpModule,
 FormsModule,
 JsonpModule,
 AppRoutingModule
 ],
 providers: [
 LocalStorageService, 
 DataObservableService, 
 PagerService, 
 OrderByPipe, 
 SafeHtmlPipe,
 ConfigService,
 {
 provide: APP_INITIALIZER,
 useFactory: initConfig,
 deps: [ConfigService],
 
 
 multi: true
 }
 ],
 bootstrap: [AppComponent]
})
export class AppModule { }
</span>

In our config.service.ts file we will retriev our JSON Config data and our Paroducts Data. We will use a combination of both Promise and Observable for best results.

Promise – A Promise handles a single event when an async operation completes or fails.

Observable – An Observable is like a Stream that allows you to pass zero or more events where the callback is called for each event. Observable is preferred over Promise because it provides the features of Promise and more. With Observable it doesn’t matter if you want to handle no event, one event or multiple events. You can utilize the same API in each case.

As shown below is our config.service file in which we will load our Config.json file using a Promise and then we will read DATA_SOURCE to see what method to use to load our Products.json file.

<span id="ArticleContent22">
import { Inject, Injectable } from '@angular/core';
import { Http, Jsonp, Response, Headers, RequestOptions, URLSearchParams } from '@angular/http';
import { DomSanitizer, SafeResourceUrl, SafeHtml, SafeUrl, SafeStyle} from '@angular/platform-browser';
import { Observable } from 'rxjs/Observable';

import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { Config } from '../services/config.static';

@Injectable()
export class ConfigService {

 
 private static _config: Object = null;
 
 
 
 private static _products: Object = null;
 private static _promise: Promise<any> = null;
 private retryCount = 2;
 headers: Headers;
 options: RequestOptions;

 constructor(private http: Http,
 private _jsonp: Jsonp,
 private sanitizer: DomSanitizer) {
 this.headers = new Headers(
 {
 'Content-Type': 'application/json',
 'Accept': 'q=0.8;application/json;q=0.9',
 'async': true,
 'dataType': 'jsonp'
 }); 
 this.options = new RequestOptions({ headers: this.headers });
 ConfigService._promise = this.load();
 }

 public config(): any { return ConfigService._config; }
 public getProducts(): any { return ConfigService._products; }
 public configKey(key: any) { return ConfigService._config[key] }
 getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }

 load() {
 let local_base = './assets/data/' + 'config' + '.json?'; 
 
 let local_rnd = 'rnd=' + this.getRandomInt(1, 500);
 let local_url = local_base + local_rnd;
 return new Promise((resolve, reject) => {
 this.http.get(local_url)
 .map((response: Response) => response.json())
 .catch((error: any) => {
 console.error(error);
 return Observable.throw(error.json().error || 'Server error');
 })
 .subscribe((data) => {
 ConfigService._config = data;
 
 
 let request: any = null;
 switch (data.DATA_SOURCE) {
 case 'local': {
 local_base = './assets/data/' + 'products' + '.json?'; 
 local_rnd = 'rnd=' + this.getRandomInt(1, 500);
 local_url = local_base + local_rnd;
 request = this.http.get(local_url);
 } break;
 case 'remote': {
 
 let _store = '';
 let _userid = '';
 const jsonp_base = data.JSONP_DOMAIN1;
 let jsonp_param = 'store=' + _store + '&userid=' + _userid;
 jsonp_param = jsonp_param + '&methodName=Feeds&jsonp=JSONP_CALLBACK';
 let jsonp_rnd = '&rnd=' + this.getRandomInt(1, 500);
 let jsonp_url = jsonp_base + jsonp_param + jsonp_rnd;
 request = this._jsonp.get(jsonp_url, this.options);
 } break;
 case 'default': {
 console.error('Environment file is not set or invalid');
 resolve(true);
 } break;
 }
 if (request) {
 request
 .retry(this.retryCount)
 .map( (res) => {
 let products = res.json();
 this.checkProducts(products);
 return products;
 })
 .catch((error: any) => {
 console.error('Error reading ' + data.DATA_SOURCE + ' configuration file');
 })
 .subscribe((responseData) => {
 ConfigService._products = responseData;
 resolve(true);
 });
 } else {
 console.error('Env config file "env.json" is not valid');
 resolve(true);
 }
 });
 });
 }

 checkProducts(prods: any) {
 if (prods) {
 prods.forEach((data) => {
 
 data.link = this.getVideoEmbed(data.tube, data.videoid);
 data.videopage = this.sanitizer.bypassSecurityTrustResourceUrl(data.link);
 });
 };
 }
 
}
</any></span>

Some people may have trouble getting JSONP to work so I will explain some of the things you need to know. You can run a JSONP server easily on your server with a few lines of PHP code or you can use C# .NET etc.  The design concept I used for my JSONP server was that instead of having multiple generic handlers or a single handler with lots of switch/if statement I decided to use a single generic handler with Factory Design Pattern. The Factory returns a class based upon the methodName that is passed which is used to only handle that request. The Factory reads the methodName and its class from the web.config file and instantiates the handler. The generic handler requests the Factory for the handler and performs some pre/post processing. Here is a link to an article I wrote on creating a JSONP Videos & TV Commercials server using C# .NET which is what I used in testing the JSONP code in this Angular 2 Shopping Cart App.

You can DOWNLOAD my JSONP Server to Stream Videos. Movies, TV Shows, Tube Channels, and TV Ads from Hunndreds of Tube Servers:

C# .NET JSONP Server

Most people have problems getting this one part of the url correct:

<span id="ArticleContent22">
&methodName=Feeds&jsonp=JSONP_CALLBACK'
</span>

Look at the “jsonp” in the line above – the letters is determined by your JSONP sever and will vary from server to server. In my C# JSONP Server I used “jsonp” but you will also see in other servers “callback”, or just “c” but its value is based on the server. In other words, don’t just use what you commonly see in articles like “callback” but check to see what the JSONP server you are connecting to requires.

Using Our Pre-Loaded Config & Products Data

Retrieving our Config and Products Data is now easy to do in any of our views as follows.

<span id="ArticleContent22">
this.config = this.configService.config();
// alert('Configurations: '+ JSON.stringify(this.config));


this.products = this.configService.getProducts();
// alert('Configurations: '+ JSON.stringify(this.products));
</span>

I added a file called config.static to illustrate another approach and perhaps better approach you can use for global configuration files. Using this approach is illustrated below.

<span id="ArticleContent22">
import { Config } from 'app/services/config.static';
alert(Config.CONFIG.STORE_BG_IMAGES[0]);
</span>

Our Angular 2 Slide Button Pager

You can see our PagerService buttons shown below.

Our pager is actually fairly simple and the code for it is as follows.

<span id="ArticleContent22">
<table style="float:right;">
 <tr><td>
 <!--
 <ul *ngIf="pager.pages && pager.pages.length" class="pagination">
 <li [ngClass]="{disabled:pager.currentPage === 1}">
 <a (click)="setPage(1)">First</a>
 </li>
 <li [ngClass]="{disabled:pager.currentPage === 1}">
 <a (click)="setPage(pager.currentPage - 1)">Previous{{page}}</a>
 </<li>
 <li [ngClass]="{disabled:pager.currentPage === pager.totalPages}">
 <a (click)="setPage(pager.currentPage + 1)">Next</a>
 </<li>
 <li [ngClass]="{disabled:pager.currentPage === pager.totalPages}">
 <a (click)="setPage(pager.totalPages)">Last</a>
 </<li>
 </<ul>
 </<td></<tr>
</table>
</span>

Playing Embed Videos in Angular 2

In our app we retrieve videos from the hundreds of tube servers that allow embedding in web pages. In addition to displaying millions of movies and all kinds of videos this code will also display YOUR monetized videos from these Tube Servers like YouTube among movies and other videos. In our ConfigService we apply in checkProducts the embed format for various tube servers as follows.

<span id="ArticleContent22">
checkProducts(prods: Product[]) {
 if (prods) {
 prods.forEach((data) => {
 // Get embed format for tube servers like youtube, vimeo, youku, etc.
 data.link = this.getVideoEmbed(data.tube, data.videoid);
 data.videopage = this.sanitizer.bypassSecurityTrustResourceUrl(data.link);
 });
 };
}
</span>

The Angular 2 Product View

This view shows more details about a product and also allows users to add or remove the product in/from the shopping cart and shows how many of the product are added to the cart. You can display a video of the product or an image. If an image of the product is displayed then clicking on the image will popup a dialog showing a larger view of the image. You can see below what the Product View looks like with an image displayed.

The Products Module uses the ConfigService to get the products data and then selects whatever “id” was passed by the router.

<span id="ArticleContent22">
// private route: ActivatedRoute 
// get URL parameters via Route
this.sub = this.route
 .params
 .subscribe(params => {
 this.params = params['id'];
 this.getProducts();
});

getProducts() {
 this.prods = (this.configService.getProducts()).filter(prods => 
 ((prods.sku === this.params) || (this.params === '')) );
 window.scrollTo(0, 0);
}
</span>

The Angular 2 Cart View

Our CartModule View calls CartService in cart.service.ts which uses Observable on localStorage as follows.

<span id="ArticleContent22">loadItems(): Observable<any> {
 let items = localStorage != null ? localStorage[this.cartName + '_items'] : null;
 if (items != null && JSON != null) {
 try {
 items = JSON.parse(items);
 for (let i = 0; i < items.length; i++) {
                let item = items[i];
                if (item.sku != null && item.productname != null && item.unitprice != null 
                    && item.saleprice != null && item.showsale != null 
                    && item.quantity != null && item.sh != null && item.faux != null) {
                    item = new this.cartItem(item.sku, item.productname, item.unitprice, 
                        item.saleprice, item.showsale, item.quantity, item.sh, item.faux);
                    this.items.push(item);
                }
            }
        }
        catch (err) {
            // ignore errors while loading...
        }
    }
    return items;
}
</any></span>

Users can edit the cart and checkout using PayPal, Google Wallet, and Stripe. Below is what the Cart View looks like on a laptop.

  1. PayPal. This payment method specifies the merchant account or BuyNow account(not a merchant account) to use for payment. To use PayPal, you have to create either a BuyNow Account or a merchant account with PayPal. You can do that here: https://www.paypal.com/webapps/mpp/merchantaypal.com/webapps/mpp/merchant
  2. Google Wallet. This payment method requires that you create a merchant account with Google. You can do that here: https://developers.google.com/commerce/wallet/digital/training/getting-started/merchant-setup
  3. Stripe. This payment method allows you to embed their API on a websites to accept payments, without the need of getting a merchant account. Stripe has no setup fees, monthly fees, minimum charges, validation fees, card storage fees, or charges for failed payments. Stripe has a 7-day waiting period for transactions to be completed so that Stripe can profile the businesses involved and detect fraud. https://stripe.com

As I explained earlier you can use the compiled files as a Mobile Shopping Cart that you can install on any Mobile Device or as a web based Angular 2 Shopping Cart on your website.


Shown on the left I am using it on a Mobile Phone for my comic book collection.


The best feature is that I can set a DISTRIBUTER_ID in my Config.json file and give a link or the folder with this app to someone who wants to sell my products and get paid a commission.

Very Cool GUI & Hover Effects

To start with I wanted to include a Pinterest Style Layout so I decided to use a common one that I have seen used often in shopping carts, namely, Codrops famous ViewModeSwitch, that you can find at: https://github.com/codrops/ViewModeSwitch.  ViewModeSwitch is a CSS Pinterest Style Layout that is used n many commercial shopping and it works well with AngularJS with minimal changes.

I decided to add a collection of hover animations and I wrote an animation editor that is in the menu to select and apply different hover animations to different objects in the cart. I loooked at a number of hover libraries and picked one called Hover that I really liked by Ian Lunn which you can explore on his GitHub at: https://github.com/IanLunn   

To apply an effect you simply select the Effects tab in the menu and then selct one of the green radio buttons, namely: storeimg, store pill, carousel img, or carosel pill. Note that the carousel options are only avaiable if you have added the JavaScript for the Super Slick Carousel.  After selecting the object you want to apply the hover effect to simply click on the effect you want in the list belwo. You can easily define new objects to apply these effects to in the views.

The hover effects from the Hover library are applied as follows:

<span id="ArticleContent22">
 changeAnimation(effect_name) {
 event.preventDefault(); 
 this.isOpenNavbarAnimation = !this.isOpenNavbarAnimation;
 let e = '';
 if (this.myModel === 'carousel_img_video') {
 e = '.carousel_img_video';
 } else if (this.myModel === 'carousel_pill') {
 e = '.carousel_pill';
 } else if (this.myModel === 'store_img_video') {
 e = '.store_img_video';
 } else if (this.myModel === 'store_pill') {
 //e = '.nav-pills li';
 e = '.store_pill';
 }
 if (e.length > 0) {
 $(e).removeClass(function (index, css) {
 return (css.match(/(^|\s)hvr-\S+/g) || []).join(' ');
 });
 $(e).addClass(effect_name);
 }
 if (effect_name.length > 0) {
 $(e).removeClass(function (index, css) {
 return (css.match(/(^|\s)hvr-\S+/g) || []).join(' ');
 });
 $(e).addClass(effect_name);
 }
 };
</span>

The controls below set the effects above:

<span id="ArticleContent22">
 // create a radioButtonGroup for our apply effects options
 public myOptions = [
 { id: 'store_img_video', name: 'store img', disabled: false, showinfo: '' },
 { id: 'store_pill', name: 'store pill', disabled: false, showinfo: '' },
 { id: 'carousel_img_video', name: 'carousel img', disabled: false, showinfo: '' },
 { id: 'carousel_pill', name: 'carousel pill', disabled: false, showinfo: '' }
 ];
</span>

Bootstrap 3 Navbars

I used Bootstrap 3 but NOT ui.bootstrap because ui.bootstrap gives me headaches trying to keep up with their changes. Bootstrap 3 has navbars where it easy to change the look-and-feel of the navbars from in side your app using AngularJS as demonstrated below in the shopping cart. To create the gradient in these navbars I used the gradient editor at: http://www.colorzilla.com/gradient-editor/.​ 

For the Navbars I applied Color Coordination with the Navbars so that each navbar would have its own Hover Effect when hovering over the pills created by Codrops famous ViewModeSwitch,  The code that changes the background color and enlarges the image as well as dozens of other cool hover effects are applied using the Hover library.  A few other transition effects are from the project on Codrops related to ViewModeSwitch called ResponsiveIconGrid at: 

http://tympanus.net/Blueprints/ResponsiveIconGrid/#

In each Navbar style sheet we have that hover gradient css for the pills as follows.

Which produces the different hover effects for each navbar. However, we need to turn off many of these effects when the shopping cart is on a mobile device and the CSS in this project does that to achieve a nicer display on mobile devices. Dozens of samples of all kinds of animation effects for Codrops famous ViewModeSwitch are available on Codrops.  However remember that animation effects are distracting and take a reader’s attention away from the ad copy for your products so use them sparingly.  Below you can see there are a large number of effects you can apply to any object in any view. The red button in the tab menu dropdown allows you remove any hover effect you have applied.

For additional glyphicons check out:

http://glyphicons.bootstrapcheatsheets.com/

One of the things you have to decide is how to handle closing of expanded dropdowns when there is an off menu click. I tried several approaches to this and finally decided on the following approach to handle off menu clicks to close any expanded dropdowns in our NavbarComponent as shown below.

<span id="ArticleContent22">
@Component({
 selector: 'app-navbar',
 templateUrl: './navbar.component.html',
 styleUrls: ['./navbar.component.scss'],
 host: {
 '(document:click)': 'offNavClick($event)',
 },
 providers: [WindowService, DataObservableService, LocalStorageService, CartService]
})

 constructor(private _eref: ElementRef) { }

 offNavClick(event) {
 // Off menu code to close dropdowns
 if (!this._eref.nativeElement.contains(event.target)) {
 this.isOpenNavbarTheme = false;
 this.isOpenNavbarAnimation = false;
 this.isOpenNavbarVideoSites = false;
 }
 }
</span>

Bootstrap 3 Gradient Buttons

I don’t like the look of Bootstrap 3 buttons so I decided to give them some depth as shown below. To do this I used a really cool Bootstrap 3 Editor that creates buttons with a gradient and mouse over and mousedown eeffects with a single block of CSS code at: http://charliepark.org/bootstrap_buttons/

Adding Features to Your Angular 2 TV Shopping Cart Application

You can use the ng generate command to add features to the app by going to the directory you want to add the module, service, etc. to using one of the commands below:

  • ng generate class my-new: adds a class to your application
  • ng generate component my-new: adds a component to your application
  • ng generate directive my-new: adds a directive to your application
  • ng generate enum my-new: adds an enum to your application
  • ng generate module my-new: adds a module to your application
  • ng generate pipe my-new: adds a pipe to your application
  • ng generate service my-new: adds a service to your application

For example to add a Cart Service you would go to the directory you want to add it to and type:

<span id="ArticleContent22">
C:\Angular2\cart-app\cd src\app\services
C:\Angular2\cart-app\src\app\services>ng generate service cart</span>

Conclusion

I also like Bootstrap, because it makes it easy to create attractive, responsive HTML layouts. In addition to a nice set of styles and icons, Bootstrap also provides some JavaScript components that you can use to enhance your UIs with things like tooltips, pop-overs, menus, etc. You can learn about Bootstrap here: http://twitter.github.io/bootstrap/.

 

LEAVE A REPLY