Who loves creating apps.

Tag: angular

Fetch data with auto-incremented ID


Angular and PHP: A Formidable Duo

Angular, a platform and framework for building single-page client applications using HTML and TypeScript, offers developers a way to create high-performance web applications that are easy to maintain. On the server side, PHP stands as a widely-used scripting language that is especially suited for web development. When combined, Angular and PHP can serve as the foundation for creating dynamic, data-driven web applications that are both efficient and scalable.

Angular Service (TypeScript)

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  constructor(private http: HttpClient) { }

  fetchData(): Observable<any> {
    return this.http.get('api/fetchData.php');
  }
}

PHP Backend (fetchData.php)

<?php
header('Content-Type: application/json');

// Database connection
$host = 'your_database_host';
$dbname = 'your_database_name';
$user = 'your_database_user';
$pass = 'your_database_password';
$dsn = "mysql:host=$host;dbname=$dbname";
$conn = new PDO($dsn, $user, $pass);

// Fetch data with auto-incremented ID
$stmt = $conn->prepare("SELECT * FROM your_table_name ORDER BY id DESC");
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

echo json_encode($results);
?>

Emphasizing Database Reliability and Efficiency

Reliable database systems are the backbone of any web application. They ensure data integrity, security, and accessibility. The level of information a database manages and its structuring significantly impact the application’s performance. Using auto-increment keys in databases simplifies record tracking and eliminates the need for manual ID management, enhancing data consistency and integrity.

Spotlight on Essential Database Tools

Exploring the landscape of database management, several tools stand out for their utility, versatility, and support in enhancing database reliability:

  • Alwaysdata Admin Interface: Provides a comprehensive web hosting platform with a user-friendly interface for database management, making it easier for developers to deploy and manage their web applications and databases.
  • DBeaver: An open-source universal database tool that supports all major databases, offering a sophisticated interface for database administrators and developers to manage and analyze databases.
  • DataGrip by JetBrains: A professional database management tool that offers context-aware code completion, code inspections, and version control integration, tailored for database development.
  • VSCode MySQL Client2: An extension for Visual Studio Code that turns it into a powerful MySQL client, supporting database management directly from the IDE.

Conclusion

The combination of Angular and PHP for web development, coupled with the strategic use of advanced database management tools, can significantly elevate the quality and performance of web applications.

Python-Django backend for data processing and an Angular front-end for the user interface

Code Algorithm with Comments

process.

# Django backend part

# models.py
from django.db import models

# Define the Article model to store the article data
class Article(models.Model):
    title = models.CharField(max_length=255)
    introduction = models.TextField()
    early_days = models.TextField()
    rise_of_frameworks = models.TextField()
    modern_era = models.TextField()
    emerging_technologies = models.TextField()
    conclusion = models.TextField()

    def __str__(self):
        return self.title  # Representation of the model instance

# views.py
from django.views.generic import CreateView
from .models import Article
from .forms import ArticleForm  # Import the form for Article

# View to handle the creation of an Article
class ArticleCreateView(CreateView):
    model = Article
    form_class = ArticleForm
    template_name = 'article_create.html'
    success_url = '/articles/'

    # Example method to handle form submission
    def form_valid(self, form):
        # Logic to process input data and generate article content
        # This is where you can integrate the article generation logic
        return super().form_valid(form)

# Angular frontend part

# article.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ArticleService {
  constructor(private http: HttpClient) {}

  // Method to submit user data to the backend and get the article
  submitData(userData: any): Observable<any> {
    return this.http.post('/api/articles/', userData);
  }
}

# article.component.ts (simplified for clarity)
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { ArticleService } from './article.service';

@Component({
  selector: 'app-article-form',
  templateUrl: './article-form.component.html'
})
export class ArticleFormComponent {
  articleForm = new FormGroup({
    userData: new FormControl('')
  });

  constructor(private articleService: ArticleService) {}

  onSubmit() {
    // Call the service to submit the form data
    this.articleService.submitData(this.articleForm.value).subscribe(response => {
      // Handle the response here, such as displaying the generated article
    });
  }
}

Signature

For more insights and updates on web development, feel free to check my projects and thoughts at github.com/kvnbbg.

Angular : How ngModel Works

In the labyrinthine world of web development, the quest for efficient data binding mechanisms is perpetual. Angular, a champion among web development frameworks, offers a potent spell known as ngModel for binding form elements such as <input>, <select>, or <textarea> to component properties. This syntax, affectionately dubbed the “banana in a box” syntax, combines square brackets [ ] for property binding and parentheses ( ) for event binding, creating a two-way data binding conduit.

<input [(ngModel)]="task.title">

In the example above, task.title is a property of the component class. The [(ngModel)] directive weaves a two-way binding between the <input> element’s value and this property. Thus, as a user inscribes text into the input, task.title in the component updates in real-time, and vice versa.

Achieving similar functionality without Angular

Handling form submissions and data bindings.

<form id="taskForm">
  <label for="taskTitle">Task Title:</label>
  <input type="text" id="taskTitle" name="title">
  <button type="submit">Submit</button>
</form>
document.addEventListener('DOMContentLoaded', function() {
  const form = document.getElementById('taskForm');

  form.addEventListener('submit', function(event) {
    event.preventDefault();
    const taskTitle = document.getElementById('taskTitle').value;
    console.log('Task Submitted:', taskTitle);
  });
});

Purpose of ngModel

ngModel serves as a beacon, illuminating the path to simplified form handling in Angular applications by:

  • Simplifying Form Handling: It reduces the boilerplate code necessary for synchronizing the UI with the component’s data model.
  • Supporting Form Validation: Works in harmony with Angular’s validation mechanisms to provide real-time feedback on the state of form controls.
  • Integrating with Forms API: ngModel seamlessly integrates with Angular’s Forms API, enriching both template-driven and reactive forms.

To embrace ngModel, ensure that the FormsModule is imported into your module:

import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

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

Within your component, define a model for binding:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  task = {
    title: ''
  };

  onSubmit() {
    console.log('Task Submitted:', this.task.title);
  }
}

And in the template, create a form using ngModel for two-way data binding:

<form (ngSubmit)="onSubmit()">
  <label for="taskTitle">Task Title:</label>
  <input type="text" id="taskTitle" [(ngModel)]="task.title" name="title">
  <button type="submit">Submit</button>
</form>

Requirements and Setup

To harness ngModel, the FormsModule must be imported into your Angular module:

import { FormsModule } from '@angular/forms'; 

@NgModule({ 
     declarations: [ // Your components ],
     imports: [ // Other modules, FormsModule ] 
}) 
export class YourModule { }

Limitations and Best Practices

While ngModel is a powerful ally for simpler forms, Angular’s Reactive Forms may better suit complex scenarios, offering more control and scalability.

In essence, ngModel equips Angular adventurers with an elegant tool for developing dynamic forms, streamlining the journey from template to functionality.

Angular ngModel in action

Angular for the frontend, Python and Flask for the backend, and a SQL database to anchor our data.

Setting Up the Project 🛠️

Angular Setup

ng new task-app
cd task-app
ng serve

Python & Flask Backend

python -m venv venv
source venv/bin/activate

With our environment consecrated, Flask stands ready to breathe life into our server-side logic.

Integrating SQL Database 🗃️

The heart of our application—a SQL database—is next. Here, Flask SQLAlchemy weaves together our data model:

from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///tasks.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class Task(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)

@app.before_first_request
def create_tables():
    db.create_all()

@app.route('/task', methods=['POST'])
def add_task():
    data = request.get_json()
    new_task = Task(title=data['title'])
    db.session.add(new_task)
    db.session.commit()
    return jsonify({'message': 'Task created successfully'}), 201

@app.route('/tasks', methods=['GET'])
def get_tasks():
    tasks_query = Task.query.all()
    tasks = [{"id": task.id, "title": task.title} for task in tasks_query]
    return jsonify({'tasks': tasks})

@app.route('/task/<int:id>', methods=['PUT'])
def update_task(id):
    data = request.get_json()
    task = Task.query.filter_by(id=id).first()
    if not task:
        return jsonify({'message': 'Task not found'}), 404
    task.title = data['title']
    db.session.commit()
    return jsonify({'message': 'Task updated successfully'})

@app.route('/task/<int:id>', methods=['DELETE'])
def delete_task(id):
    task = Task.query.filter_by(id=id).first()
    if not task:
        return jsonify({'message': 'Task not found'}), 404
    db.session.delete(task)
    db.session.commit()
    return jsonify({'message': 'Task deleted successfully'})

if __name__ == '__main__':
    app.run(debug=True)

CSRF Protection with Angular

Angular, with its built-in CSRF defenses, ensures our application is fortified against cross-site request forgery:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class TaskService {
  constructor(private http: HttpClient) {}

  addTask(taskData: any) {
    return this.http.post('/api/tasks', taskData);
  }
}

This service acts as a conduit between our Angular frontend and Flask backend, ensuring tasks are managed with grace and efficiency.

CSRF Configuration in Flask

Ensuring Flask is prepared to parry CSRF attempts is paramount. Flask-WTF lends its strength to our defenses:

import os
from flask import Flask, render_template_string
from flask_wtf.csrf import CSRFProtect

app = Flask(__name__)
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', os.urandom(24))

csrf = CSRFProtect(app)

@app.route('/', methods=['GET', 'POST'])
def index():
    return render_template_string("...")

if __name__ == '__main__':
    app.run(debug=True)

With CSRFProtect invoked, our application is shielded, allowing us to focus on crafting user experiences without fear.

Let’s methodically address these issues to pave the way for a flawless application startup.

1. Directory public/ does not exist

The absence of a public/ directory was the first hurdle. This directory is essential for serving files through the PHP server.

  • Ensure the public/ Directory Exists: I created the missing directory with the command:

    mkdir -p /home/kevin/Documents/Github/task-app/public

    and relocated the necessary server-served files into this newly forged directory.

  • Correct the Directory Path: Realizing the public/ directory existed but was elsewhere, I updated the npm run php script in the package.json to align with the correct path, ensuring harmony between my directory structure and server expectations.

2. Node.js Odd Version Warning

While not critical for development, it hinted at potential instability for production.

  • Switch to an LTS Version of Node.js: I turned to nvm (Node Version Manager) to adopt a more stable, even-numbered LTS version of Node.js, casting:
    nvm install 16 && nvm use 16

    This ensured a foundation of stability and long-term support for my application.

3. Angular Version Compatibility Issue

The most vexing issue arose from a discord between the Angular version (17.3.1) in use and the installed Angular CLI version, leading to compatibility concerns.

  • Update Angular CLI: To mend this rift, I updated both the global and local project’s Angular CLI to versions that resonate with Angular 17, executing:

    npm install -g @angular/cli@latest && npm install @angular/cli@latest

    Utilizing npx ng serve enabled the project’s specific version of Angular CLI to come forth.

  • Follow Angular Update Guide: For a tailored path through this conundrum, I sought guidance from the Angular Update Guide, which provided a map of instructions specific to my journey from current to desired Angular versions.

After Addressing These Concerns

Embarking on npm start once more brought me closer to a seamless application startup. Should you face similar beasts, remember to isolate each problem and apply the fitting solution with precision and care.

Victory Screenshot from task-app

Armed with knowledge and experience from these encounters, I encourage you to face your development challenges with courage and curiosity. Remember, every problem bears a solution, each bug a lesson in disguise.

Let’s begin our coding quest

Overview

  1. Frontend Journey with Angular: Angular acts as our herald, dynamically presenting error messages to the user. It’s flexible enough to communicate with the backend, fetching the specifics of the error encountered.
  2. Backend Quest with PHP: The PHP backend serves as the keeper of knowledge, providing details about the errors through an API endpoint that our Angular front-end can consult.

Step 1: Setting Up the Angular Environment

The first step in our quest is to prepare our Angular environment:

ng new error-handling-app
cd error-handling-app
ng serve

Step 2: Enchanting the Angular AppComponent

To capture and display errors, we modify the src/app/app.component.ts:

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Error Handling App';
  errorMessage: string = '';

  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.fetchError();
  }

  fetchError() {
    this.http.get<{error: string}>('/api/error')
      .subscribe(
        response => this.errorMessage = response.error,
        error => this.errorMessage = 'Failed to fetch error details.'
      );
  }
}

And within the src/app/app.component.html, we conjure the error message into visibility:

<div class="container">
  <h1>Error Occurred</h1>
  <p>{{ errorMessage }}</p>
  <a href="/">Go Back to Home</a>
</div>

Step 3: Crafting the Backend (PHP) API Endpoint

On the PHP side, we establish an API endpoint that our Angular front-end will consult to glean error details:

<?php
header('Content-Type: application/json');

$response = ['error' => 'An unexpected error occurred. Please try again later.'];

echo json_encode($response);
?>

Step 4: Uniting Frontend and Backend

  • Angular App: After building the Angular app (ng build), it can be served through a web server or intertwined within your PHP application.
  • PHP Backend: Make sure the PHP backend is accessible to the Angular app, especially considering CORS if they’re hosted separately.

Screenshot 1

Screenshot 2

Screenshot 3

Screenshot 4

Screenshot 5

Angular and much more

Angular’s evolution has taken the development world by storm, beginning with its significant announcement at the ng-Europe conference back in October 2014. Since then, it has become a cornerstone for developing robust and dynamic web applications. This article guides you through setting up a new Angular project named “Task,” emphasizing the creation of a comprehensive task management application.

The Beginning 🚀

The journey into Angular begins with the Angular CLI, a powerful toolset for initializing, developing, and maintaining Angular applications. To kickstart your project:

  1. Angular CLI Installation:
    • Ensure you have Node.js installed, then proceed with Angular CLI installation using npm:
    • npm install -g @angular/cli
  2. Project Initialization:
    • Create a new Angular project “Task” with routing enabled and SCSS for styles:
    • ng new Task --routing=true --style=scss
  3. Component Generation:
    • Generate essential components for managing tasks:
    • ng generate component Tasks
    • ng generate component TaskDetail
    • ng generate component AddTask
  4. Routing Setup:
    • Configure routing in app-routing.module.ts to navigate between components seamlessly:
    • import { NgModule } from '@angular/core';
    • import { RouterModule, Routes } from '@angular/router';
    • import { TasksComponent } from './tasks/tasks.component';
    • import { TaskDetailComponent } from './task-detail/task-detail.component';
    • import { AddTaskComponent } from './add-task/add-task.component';
    • const routes: Routes = [
    • { path: 'tasks', component: TasksComponent },
    • { path: 'task/:id', component: TaskDetailComponent },
    • { path: 'add-task', component: AddTaskComponent },
    • { path: '', redirectTo: '/tasks', pathMatch: 'full' },
    • ];
    • @NgModule({
    • imports: [RouterModule.forRoot(routes)],
    • exports: [RouterModule]
    • })
    • export class AppRoutingModule { }
  5. Backend Integration:
    • Implement TaskService to perform CRUD operations against a backend API:
    • import { Injectable } from '@angular/core';
    • import { HttpClient } from '@angular/common/http';
    • import { Observable } from 'rxjs';
    • import { Task } from './task';
    • @Injectable({
    • providedIn: 'root'
    • })
    • export class TaskService {
    • private apiUrl = 'http://yourapi/tasks';
    • constructor(private http: HttpClient) { }
    • getTasks(): Observable {
       return this.http.get(this.apiUrl);
      }
      
      getTask(id: number): Observable {
       return this.http.get(${this.apiUrl}/${id});
      }
      
      addTask(task: Task): Observable {
       return this.http.post(this.apiUrl, task);
      }
      
      updateTask(task: Task): Observable {
       return this.http.put(${this.apiUrl}/${task.id}, task);
      }
      
      deleteTask(id: number): Observable {
       return this.http.delete(${this.apiUrl}/${id});
      }
      }
  6. Frontend Interaction:
    • Utilize TaskService in TasksComponent to interact with the backend and display tasks:
    • import { Component, OnInit } from '@angular/core';
    • import { TaskService } from '../task.service';
    • import { Task } from '../task';
    • @Component({
    • selector: 'app-tasks',
    • templateUrl: './tasks.component.html',
    • styleUrls: ['./tasks.component.scss']
    • })
    • export class TasksComponent implements OnInit {
    • tasks: Task[];
    • constructor(private taskService: TaskService) { }
    • ngOnInit() {
    •  this.getTasks();
    • }
    • getTasks(): void {
    •  this.taskService.getTasks()
    •    .subscribe(tasks => this.tasks = tasks);
    • }
    • }
  7. Styling:
    • Define styles for your task components to ensure a user-friendly interface:
    • .task-container {
    • margin: auto;
    • width: 50%;
    • padding: 20px;
    • box-shadow: 0 4px 8px rgba(0,0,0,0.2);
    • }
    • .task-item {
    • display: flex;
    • justify-content: space-between;
    • padding: 10px;
    • margin-top: 10px;
    • border: 1px solid #ccc;
    • border-radius: 5px;
    • }
    • .task-title {
    • font-size: 18px;
    • }
    • .delete-button {
    • cursor: pointer;
    • color: red;
    • }

Setting Up Protection 🛡️

Securing your application is paramount, and Angular aids this with built-in CSRF protection. For back-end CSRF protection, use Node.js/Express with csurf and cookie-parser. Ensure Angular’s HttpClientModule is imported in your app.module.ts for front-end CSRF protection.

Building the Task Application’s UI 🎨

The UI of your task application is the face of your project. Angular provides directives like ngFor for listing tasks and ngModel for two-way data binding, significantly easing the development process.

Leveraging Angular Libraries and Frameworks 📚

To further enhance your application, Angular offers integration with various libraries and frameworks like Angular Material for UI components, NGRX for state management, and RxJS for handling asynchronous operations.

Conclusion

The journey through Angular development is filled with vast possibilities. Utilizing Angular CLI, incorporating essential components, and leveraging external libraries can significantly enrich your application, making “Task” a robust, dynamic, and user-friendly task management tool.

© 2024 Kvnbbg.fr

Theme by Anders NorénUp ↑

Verified by MonsterInsights