Saturday, March 28, 2020

HighCharts with Angular - Part 2 - Stock Portfolio with Dashboard

In continuation of previous post, now I try to implement the final chapter of the book, https://www.apress.com/gp/book/9781484257432.

The app is live: https://stock-portfolio.zoltanhalasz.net/
Zip repo of client side:



The back-end, which uses an In-Memory database, and Asp.Net Core Web Api, is based on Chapter 7, will use a Yahoo Finance Wrapper, and provide data to the Angular app, as shown in the Web API controller (see book starting with, pages 259).

The Asp.Net Core back-end is live under:

https://stockapi.zoltanhalasz.net/api/getstock

Zip Repo of server side:

I changed the back-end and front-end a little bit, correcting Typos, Formatting (indentation) and changing a little bit the main Stock class of the project.







HighCharts with Angular - Part 1 - Introduction

To continue the idea from the previous posts, my goal is to gather a number of libraries that can make my business applications look more professional, adding new functionalities and features.


One of these libraries is HighCharts, that can be integrated easily into Asp.Net and Angular (and Javascript) projects.

I would add here this great book which started my interest and whose projects I looked at and tried to implement some of its content.


For any Angular project, we can add the HighChart libraries using the below npm commands:
1.
npm install highcharts –save
This command will add Highcharts dependencies into your project.

2.
npm install highcharts-angular –save
The Highcharts angular wrapper is open source. It provides vibrant
and dynamic feature visualization for Highcharts within an Angular
application.


The example attached will be an updated (corrected, as there are some typos and formatting issues in the book) version of the Chapter 5 example: Angular-Highcharts UI Application (page 125).
I added into my Angular App the following examples also: page 140 - 159: DrillDown Event, LegendItem Event, CheckBoxClick Event.

My application is online:
https://highcharts-angular1.zoltanhalasz.net/

Code can be downloaded :
(you have to add npm install after unzipping it)

The following routes are active:
A. adding a new student with marks:
https://highcharts-angular1.zoltanhalasz.net/addmarks
B. after adding them, their marks will be present under the main link
https://highcharts-angular1.zoltanhalasz.net/



C. events with checkbox
https://highcharts-angular1.zoltanhalasz.net/checkbox
D. events with legenditem click
https://highcharts-angular1.zoltanhalasz.net/legenditem
E. events with drilldown
https://highcharts-angular1.zoltanhalasz.net/drilldown



It also uses a back-end service live under the link: https://studentapi.zoltanhalasz.net/
this application also implements the .Net Wrapper of the Highchart, shown in example at the end of Chapter 5.

It is based on the book, starting with page 160, also adding an in-memory database to serve the data needed by the api controller. This will provide the back-end for the angular project above, and is called in the service typescript file of the angular project.

The code of the back-end is in this zip repo.





Tuesday, March 10, 2020

Front-End Challenge from Colt Steele: Stepper Form

In the past weeks I reviewed a bit my front-end (html-css-javascript) lessons, and also found an interesting challenge lately. It is a vanilla js challenge by Colt Steele, published on Youtube:


My solution to it:
https://github.com/zoltanhalasz/StepperForm

Working link(live project):
https://codepen.io/zoltanhalasz/project/editor/ApPwKj

Explanation:
-I am using a structure with div's with classes and id's that can be targeted by Javascript DOM manipulation.
- the script uses lots of functions, and the getElementById used to target the classes/ids
- use hide/show for the stepper form via Javascript (manipulating DOM styles)

Recommended reading:
- Javascript DOM: https://www.w3schools.com/js/js_htmldom.asp
- CSS/Html: https://www.w3schools.com/html/default.asp

Monday, March 9, 2020

From Angular to Ionic - Todo App - Tutorial






This is the Ionic 5 version of the Todo app presented in previous posts, without applying the formatting and Web Api. My goal was to practice my Angular lessons from last year, and do this with the trendy Ionic framework.

Prerequisites:
a.) javascript/angular intermediate knowledge
b.)check the following Ionic documentation https://ionicframework.com/docs/components/
Especially: button, input, card, alert.
c.) And also please check the steps for creation of simple apps in Ionic:
https://ionicframework.com/getting-started/
d.) code is commented for a better understanding. It's the angular/typescript component file that contains the whole logic, described in the comments, see repo.

Web version is live under the link:
https://ionic5-todo.zoltanhalasz.net/










Saturday, March 7, 2020

Traversy Media Tutorial Transformed into Angular




The plain javascript version of this tutorial: https://mydev-journey.blogspot.com/2020/02/expense-tracker-from-traversy-media.html

The application is live: https://ng-expenses.zoltanhalasz.net/

Zipped Repo:

Prerequisites:
1. intermediate javascript/typescript
2.  before you check my tutorial, please check the following material: https://www.positronx.io/angular-7-httpclient-http-service/
3. back-end for this angular app is identical with the javascript version backend.

Full Stack Mini ToDo-App With Angular, HttpClient, API Controller and In-Memory Database

This tutorial is an Angular version of the plain Javascript one.



The back-end will be exactly identical, for simplicity will call the API from the previous tutorial, please study the above link for this.

The application was created from scratch, new Angular 9 application, with some inspiration from the below Angular HttpClient tutorial.

Prerequisites:
1. you must have Angular 9 (or 7,8) installed on your PC
2. basic / intermediate javascript/typescript
3. review above mentioned tutorials. Web api for back-end is identical.
4. the front-end, styling belong to original tutorial from Dennis Ivy, I just transposed here to Angular.
5. basic tutorial for Angular, which teaches some of the steps: https://www.positronx.io/angular-7-httpclient-http-service/

Application is live under: https://angulartodo.zoltanhalasz.net/

Zip Repo: here.

Steps for creating the app:

1. ng new todolist

2. styling
add bootstrap: npm install bootstrap

css file include it in Angular.json

"styles": [ "node_modules/bootstrap/dist/css/bootstrap.min.css", "styles.scss" ]

in the index html file, I will include some special fonts in the head
 <link href="https://fonts.googleapis.com/css?family=Montserrat&amp;display=swap" rel="stylesheet">

app.component.css will include the formatting from Dennis Ivy's original tutorial.(see repo)

3. create class

export class todomodel {

    constructor (
        public idnumber,
        public titlestring,
        public completedboolean){
            
        }
}

4. create service - I will not copy the lengthy code here.(see repo)
Some starting points: it is a very close copy of the api service from this tutorial (also mentioned above):  https://www.positronx.io/angular-7-httpclient-http-service/

The Api link reference will be identical with the plain javascript tutorial.
'https://todolist.zoltanhalasz.net/api/TodoModels'

5. add various references to app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule }   from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { TodoService } from './todo.service';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    HttpClientModule
  ],
  providers: [TodoService],
  bootstrap: [AppComponent]
})
export class AppModule { }



6. app component html

<div class="container">
  <div id="task-container">
      <div id="form-wrapper">
          <form id="form" (ngSubmit)="onSubmit()" #todoForm="ngForm">    
                  <div class="flex-wrapper">
                    <div style="flex: 6">                      
                      <input type="text" class="form-control" id="title" required [(ngModel)]="mytodo.title" name="title"
                      #title="ngModel">
                    </div>             
                    <div style="flex: 1">
                      <button type="submit" id="submit" class="btn">Submit</button>     
                    </div>      
                  </div>                      
          </form>
      </div>
      <div id="list-wrapper">
        <div class="task-wrapper flex-wrapper" *ngFor="let item of mytodolist">
          <div style="flex:7">
            <span [className]="item.completed ? 'finish-title' : 'title'"             
            (click)="FinishTodo(item.id)">{{item.title}}</span>
          </div>
          <div style="flex:1">
            <button class="btn btn-sm btn-outline-info edit" (click)="Edit(item.id)">Edit </button>
          </div>
          <div style="flex:1">
            <button class="btn btn-sm btn-outline-danger delete" (click)="Delete(item.id)">Delete</button>
          </div>
        </div>
      </div>
  </div>
</div>
<!-- <router-outlet></router-outlet> -->


7. app.component.ts

import { ComponentOnInit } from '@angular/core';
import {todomodelfrom "./todomodel";
import { TodoService } from './todo.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
  title = 'todolist';
  // when a task is being edited  
  edited = false;
  // initialize sample todo
  mytodo = new todomodel(0,'',false);
  // this array will always store list of todos retrieved from server
  mytodolist:  todomodel [];

  //injecting the dataservice
  constructor (private dataserviceTodoService) {
  }

  // submitting the form 
  onSubmit() {      
      this.saveTodo(this.mytodo);
      // resetting the mytodo value
      this.mytodo = new todomodel(0,'',false);
    }

  saveTodo(mytodotodomodel){
    // if it is not an editing
    if (!this.edited) {
      if (this.mytodo.title==''return;
      // saving new todo
        this.dataservice.createTodo(mytodo).subscribe(data=> {
          this.displayTodoList();
      });
    }
    // if we are editing an existing todo
    else {
      this.edited=false;
      console.log('this is being edited',mytodo);
            // update existing todo
      this.dataservice.updateTodo(this.mytodo.id,this.mytodo).subscribe(data =>
        {     
          this.displayTodoList();
        }       
        );
    }    
  }

  ngOnInit(){
    this.displayTodoList();
  }

  //this function retrieves the whole array of todos from server, using api service injected
  displayTodoList() {
    this.dataservice.getTodoList().subscribe(data =>
      {
        // as the Web Api doesn't sort the list of todos, we do here in the frontend
        this.mytodolist = data.sort((a,b)=> {
          if (a.id>b.idreturn -1;
          if (a.id<b.idreturn 1;
        });
        console.log('display'this.mytodolist);
      });
  }
  //deleting an existing todo
  Delete(idnumber) { // without type info
    console.log('delete'id);    
    this.dataservice.deleteTodo(id).subscribe(data =>{
        this.displayTodoList();
      });
  }
  //editing an existing todo
  Edit(eidnumber) { // without type info
    console.log('editing',eid);
    this.mytodo = this.mytodolist.filter(x=>x.id ==eid)[0];
    this.edited = true;   
  }

    //finalizing(crossing) an existing todo
  FinishTodo(eidnumber) { // without type info
    // console.log('finishing', eid);   
    const mytodofinished = this.mytodolist.filter(x=>x.id ==eid )[0];
    mytodofinished.completed =  !mytodofinished.completed ;
    //calling the update observable
    this.dataservice.updateTodo(eid,mytodofinished).subscribe(data =>{     
        this.displayTodoList();
      });
  }

}



Tuesday, March 3, 2020

Full Stack Asp.Net Core App (Bootcamp Project) - Part 4 - The Front-End

This is the continuation of thrid part of the series.


As mentioned, all html, css and javascript is written manually (without frameworks) in the application. The html and css will not be explained here, instead, we will focus to describe in more detail the front-end Javascript (DOM manipulation) from the Notes html page, which is the main area of the whole application.

This html / javascript was learned as a bootcamp, it's not perfect, just an attempt to show the capabilities of JS in the browser, together with AJAX (Fetch API).

I recommend that the following material is reviewed before reading further:
1. https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
2. https://mydev-journey.blogspot.com/2020/02/expense-tracker-from-traversy-media.html
3. https://mydev-journey.blogspot.com/2020/02/full-stack-mini-todo-app-with.html
4. https://mydev-journey.blogspot.com/2020/02/mybooklist-another-traversy-tutorial.html

Link to Github Repo of notes page.

The below will be a succinct description of the existing html/javascript code of the notes page.

a. ) The whole start of the action is bootstrapped at the bottom of the page:

   <script>
        window.onload = () => {
            //initialization of functions and showing the notes
            getNotesForUser(myLoginUser, "Desc","(empty)");
            showColorPicker();
            addClickListeners();         
        }
    </script>
b.) there are two variables in the pagemodel, and these will be taken to the front-end and injected in the javascript code:
- user email - to be displayed at the top of the page:  Welcome @Model.LoginUserEmail!
- user id, which is crucial in the operation of notes:  var myLoginUser = @Model.LoginUserID;

c.) in the top of the page, will be  a form for the filtering and ordering of notes (div id="header")


d.) in the main of the html page, we will have a form id="new-note" that will save the new notes.

The onsubmit function is written below, saves the new notes (plus images, colors).

e.) below the main form we will have the list of notes displayed using getNotesForUser function.
This has a fetch with promise, and in the "then", we retrieve the images for the user. Both on the retrieved notes and images array, the insertNotesList(displayNotesList(notes, imgList))  is called which draws the list of notes and pictures.

f.) displayNote function will take the note with id x, and its pictures, and draws the container for the note, inserting pictures.
Note: if there are multiple pictures (allowed to update), the user is allowed to navigate between them, using clicks on the pictures. To see how it's done, please study getCarousel function.

g.) deleting a note: using the trash sign, we have a click event handler createDeleteNote on it. This will create a popup, and if "yes" is chosen, the removeNote function will delete the note from the Dom and back-end.


h.) editing a note: on the pencil icon of a note, createPopin function is invoked upon click, which will display a small form that will give the possibility to change title, content, delete pictures (all), add picture (only 1), and save the note.

i.) change the color of a note: also in the form (new note) and within each individual note: see getColorPickerHtml function. It will display a list of colors, which will change the background color of selected note, and save the color on the back-end for future use.

j.) pin-unpin: this functionality will pin a note, that means it will be shown first, irrespective of sorting/ordering of notes. The pinning will be done also on the back-end, marking the pinned property of a note also in the database. See function pinNote, and also the back-end API with the route: /api/Notes/pinnote

k.) search function - on key press in the search box, the page will send the query to the back-end using the fetch api in getNotesForUser

            getNotesForUser(myLoginUser, ordering, searchterm);

The web API behind this fetch, is able to sort the result using ordering, and find only those notes which have searchterm in title or content. The default searchterm is (empty) which will do no filtering by keyword.

l.) ordering function - in the header (Desc is default, Asc can be chosen). See above point k).

m.) error message functionality: in case of an error while saving/updating a note, a popup will appear, represented by the function: showErrorMessage.

I know, there are lots of points of improvement on the front-end, that was more or less the content of the bootcamp, and I re-created the project for two purposes: practice my Asp.Net Core Web-Api (as opposed to node.js in bootcamp), and Vanilla Javascript skills. Please feel free to comment or come with your own tutorial.



I might come with a next part of the tutorial, mentioning items that have been left out, or going
in more detail in another less discussed area.