how to implement ng2-dragula in angular 2 - html

how to implement ng2-dragula in angular 2.
My code is shared below,
****viewer.component.ts****
import { Component, Input, Output, EventEmitter } from '#angular/core';
import { Injectable } from '#angular/core';
import { Headers, Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
import { ImageViewerService } from '../services/http.services';
import { Dragula,DragulaService } from 'ng2-dragula/ng2-dragula';
#Component({
moduleId: module.id,
selector: 'viewer',
directives: [Dragula],
viewProviders: [DragulaService],
providers: [ImageViewerService, DragulaService],
templateUrl: 'viewer.component.html',
})
export class ViewerComponent {
#Output() click = new EventEmitter();
http: Http;
url: string;
obj: any;
getData: string;
postData: string;
users: any;
firtsImageToBind: any;
tile: number;
tableVisible: boolean;
status: { isopen: boolean } = { isopen: false };
localImageViewerService: ImageViewerService;
localDragulaService: DragulaService;
constructor(http: Http, imageViewerService: ImageViewerService,
localDragulaService: DragulaService) {
this.users = [1];
this.http = http;
this.localImageViewerService = imageViewerService;
this.localDragulaService = localDragulaService;
this.imageReceivedFromWebAPI();
}

Ok so a quick example showing how to implement dragula into Angular2 project first install via npm:
npm install ng2-dragula dragula --save
Next import into module:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
import {DragulaModule} from 'ng2-dragula/ng2-dragula'; // Here
#NgModule({
declarations: [
AppComponent
],
imports: [
DragulaModule, // Here
BrowserModule,
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Inside app.component.html you do this.
<div>
<div class='wrapper'>
<div class='container' [dragula]='"first-bag"'>
<div>You can move these elements between these two containers</div>
<div>Moving them anywhere else isn't quite possible</div>
<div>There's also the possibility of moving elements around in the same container, changing their position</div>
</div>
<div class='container' [dragula]='"first-bag"'>
<div>This is the default use case. You only need to specify the containers you want to use</div>
<div>More interactive use cases lie ahead</div>
<div>Make sure to check out the <a href='https://github.com/bevacqua/dragula#readme'>documentation on GitHub!</a></div>
</div>
</div>
</div>
run the project, and you'll be able to drag the text up and down i.e changing its order.
Example specified above is from dragula github page.

Related

Angular 8: not able to get message from Rest Api

I used following links https://grokonez.com/python/django-angular-6-example-django-rest-framework-mysql-crud-example-part-2-django-server and https://grokonez.com/frontend/django-angular-6-example-django-rest-framework-angular-crud-mysql-example-part-3-angular-client to create a django rest API and angular app that calls this rest.
Considering that I'm new in such kind of development so I created as a first step an App that just displays customers list.
Django rest API is fine working. I tested it with the browser:
But my problem is with the angular app, seems that it's not able to get message with the same URL: http://localhost:8000/customers
Below is my angular code:
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { AppRoutingModule, routingComponents } from './app-routing.module';
import { AppComponent } from './app.component';
import { CustomersListComponent } from './customers-list/customers-list.component';
#NgModule({
declarations: [
AppComponent,
routingComponents,
CustomersListComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { CustomersListComponent } from './customers-list/customers-list.component';
const routes: Routes = [
{ path: 'customers', component: CustomersListComponent },
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
customer.ts
export class Customer {
id: number;
name: string;
age: number;
active: boolean;
}
customer.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class CustomerService {
private baseUrl = 'http://localhost:8000/customers';
constructor(private http: HttpClient) { }
getCustomersList(): Observable<any> {
return this.http.get(`${this.baseUrl}/`);
}
}
customers-list.component.ts
import { Component, OnInit, Input } from '#angular/core';
import { Observable } from 'rxjs';
import { CustomerService } from '../customer.service';
import { Customer } from '../customer';
#Component({
selector: 'app-customers-list',
templateUrl: './customers-list.component.html',
styleUrls: ['./customers-list.component.css']
})
export class CustomersListComponent implements OnInit {
customers: Observable<Customer[]>;
constructor(private customerService: CustomerService) { }
ngOnInit() {
console.log("Hellllllllo from customers-list.component.ts ngOnInit");
this.reloadData();
}
reloadData() {
this.customers= this.customerService.getCustomersList();
}
}
customers-list.component.html
<h1>Customers {{JSON.stringify(this.customers)}}</h1>
<div *ngFor="let customer of customers" style="width: 300px;">
<h2>Hello iii</h2>
<div>
<label>Name: </label> {{customer.name}}
</div>
<div>
<label>Age: </label> {{customer.age}}
</div>
<div>
<label>Active: </label> {{customer.active}}
</div>
</div>
The result that got when calling /customers from the browser is the following:
"Routing and Navigation" message is coming from app.component.html
As you can see message Customers is displayed but everything that corresponds to the variable customers (which is the list of customers) is not displayed.
Has someone an idea what's the main cause of this issue? and how I can fix it?
Thank you in advance
You should subscribe to get the response from the API because http.get returns an observable, observable invokes only when you subscribe to it. try the following method
reloadData() {
this.customerService.getCustomersList().subscribe((res: any) => {
this.customers = res;
});
}
In your service
getCustomersList(): Observable<any> {
return this.http.get(`${this.baseUrl}/`);
}
This function returns an observable
So you should subscribe to it like this to make the request
this.customerService.getCustomersList().subscribe((res: any) => {
this.customers = res;
});
Or in your html file you can add async pipe like this
*ngFor="let customer of customers | async

TypeScript variable seems not to load the value from one file to another

I am following the tutorial here: https://coursetro.com/posts/code/154/Angular-6-Tutorial---Learn-Angular-6-in-this-Crash-Course
I currently have the code up to the section titled Fetching More Data from the API working. In short this is supposed to make a page with a bunch of users accessed through a toy API. The users are listed on a page with some personal information, and each one links to a very basic profile page displaying their details. Up to the section I mentioned above, I am successfully interfacing with the API, getting the users and displaying them and some personal information on the main page.
However, the code in this section is intended to collect an individual user's details and display them on a linked page. In trying to follow the example, my code does produce a page with the right outlines, but the value of the variable user$ and its fields like user$.name don't seem to be loaded by the details component. Where those values are supposed to show up, it's blank.
The app files:
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { UsersComponent } from './users/users.component';
import { DetailsComponent } from './details/details.component';
import { PostsComponent } from './posts/posts.component';
const routes: Routes = [
{
path: '',
component: UsersComponent
},
{
path: 'details/:id',
component: DetailsComponent
},
{
path: 'posts',
component: PostsComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.component.html
<div id="container">
<app-sidebar></app-sidebar>
<div id="content">
<router-outlet></router-outlet>
</div>
</div>
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SidebarComponent } from './sidebar/sidebar.component';
import { PostsComponent } from './posts/posts.component';
import { UsersComponent } from './users/users.component';
import { DetailsComponent } from './details/details.component';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
declarations: [
AppComponent,
SidebarComponent,
PostsComponent,
UsersComponent,
DetailsComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
data.service.ts
import { Injectable } from '#angular/core';
import {HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }
getUsers() {
return this.http.get('https://jsonplaceholder.typicode.com/users')
}
getUser(userId) {
return this.http.get('https://jsonplaceholder.typicode.com/users'+userId)
}
getPosts() {
return this.http.get('https://jsonplaceholder.typicode.com/posts')
}
}
users files:
users.component.html
<h1>Users</h1>
<ul>
<li *ngFor="let user of users$">
{{user.name}}
<ul>
<li>{{user.email}}</li>
<li>{{user.website}}</li>
</ul>
</li>
</ul>
users.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Observable } from 'rxjs';
#Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss']
})
export class UsersComponent implements OnInit {
users$: Object;
constructor(private data: DataService) { }
ngOnInit() {
this.data.getUsers().subscribe(
data => this.users$ = data
);
}
}
details files:
details.component.html
<h1>{{ user$.name }}</h1>
<ul>
<li><strong>Username: </strong> {{user$.username}}</li>
<li><strong>Email: </strong> {{user$.email}}</li>
<li><strong>Phone: </strong> {{user$.phone}}</li>
</ul>
details.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Observable } from 'rxjs';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-details',
templateUrl: './details.component.html',
styleUrls: ['./details.component.scss']
})
export class DetailsComponent implements OnInit {
user$: Object;
constructor(private data: DataService, private route: ActivatedRoute) {
this.route.params.subscribe( params => this.user$ = params.id );
console.log(this.route.params);
}
ngOnInit() {
this.data.getUser(this.user$).subscribe(
data => this.user$ = data
);
}
}
I tried logging values to the console, but I don't fully understand how TypeScript works so I don't fully know what I really should expect from these logs. In any case, in the log that I made in the details TypeScript file, it showed an object with no apparent loading errors.
this.route.params is a Observable. I am not sure what you can get by logging it.
I would suggest you add a log when subscribing to a observable and see what kind of data you really get. Like.
this.data.getUser(this.user$).subscribe(
data => {console.log(data);this.user$ = data}
);
#Adem, As Haijin comment, you must "work" a bit in subscribe parameter. The idea is that you subscribe to get the parameter, and, when you have the parameter, you ask about the user. But you need to make in the same step using switchMap
ngOnInit()
{
//You subscribe the param. When you have ask for the user
this.route.params.subscribe( params =>
{
this.user$ = params.id;
//In subscribe you ask for the user
this.data.getUser(this.user$).subscribe(
data => this.user$ = data
)
});
}
Well, really In Angular is better don't subscribe two times else using Rjxs and switchMap
ngOnInit()
{
//You subscribe the params, but you don't want the param
this.route.params.pipe(
switchMap(params =>
{ //you want return the user
return this.data.getUser(params.id)
})
).subscribe(data => this.user$ = data)
}

Angular2 won't load json file. Error: Can't resolve all parameters for AppComponent

I am trying to load a json file into my Angular app, but can't find the culprit. It keeps telling me it can't resolve all parameters of my component.
(loading the data directly from the component worked, so it has to do with the code I added most recently for loading data from a json file)
My module:
import { NgModule} from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpModule } from '#angular/http';
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/Rx';
import {Observable} from 'rxjs/Observable';
import { AppComponent } from './component.app';
#Injectable()
export class Service {
constructor(private _http: Http) {}
getData(){
return this.http.get('./assets/data/data.json')
.map(res => res.json())
}
}
#NgModule({
imports: [
BrowserModule,
HttpModule
],
declarations: [
AppComponent
],
bootstrap: [
AppComponent
],
providers: [
Service
]
})
export class AppModule {}
My component:
import { Component } from '#angular/core';
#Component({
selector: 'app',
templateUrl: './assets/partials/component-app.html',
styleUrls: ['./assets/css/component-app.css']
})
export class AppComponent {
tests: any;
constructor(private service : Service){}
ngOnInit() {
this.service.getData()
.subscribe(data => {
this.tests = data;
})
}
The error:
(index):18 Error: Error: Can't resolve all parameters for AppComponent: (?).
at CompileMetadataResolver.getDependenciesMetadata (http://localhost:3000/node_modules/#angular/compiler//bundles/compiler.umd.js:14404:21)
at CompileMetadataResolver.getTypeMetadata (http://localhost:3000/node_modules/#angular/compiler//bundles/compiler.umd.js:14301:28)
at CompileMetadataResolver.getDirectiveMetadata (http://localhost:3000/node_modules/#angular/compiler//bundles/compiler.umd.js:14074:30)
at eval (http://localhost:3000/node_modules/#angular/compiler//bundles/compiler.umd.js:14167:51)
at Array.forEach (<anonymous>)
at CompileMetadataResolver.getNgModuleMetadata (http://localhost:3000/node_modules/#angular/compiler//bundles/compiler.umd.js:14161:51)
at RuntimeCompiler._compileComponents (http://localhost:3000/node_modules/#angular/compiler//bundles/compiler.umd.js:16803:49)
at RuntimeCompiler._compileModuleAndComponents (http://localhost:3000/node_modules/#angular/compiler//bundles/compiler.umd.js:16741:39)
at RuntimeCompiler.compileModuleAsync (http://localhost:3000/node_modules/#angular/compiler//bundles/compiler.umd.js:16732:23)
at PlatformRef_._bootstrapModuleWithZone (http://localhost:3000/node_modules/#angular/core//bundles/core.umd.js:6954:29)
data.json, I need to loop through test_cases and Test_steps:
{
"test_run_id": "A233-CA92-3293-B9AA",
"app_name": "Chewy.com",
"time_stamp": "2018-01-20T12:00:00Z",
"test_cases": [
{
"test_name": "View dog bone",
"status": true,
"test_steps": [
{
"step_name": "Click Dog Category",
"screenshot": "file1.png",
"launch_times": [
100,
134,
123
],
HTML:
<section class="tested-app" *ngFor = "let item of tests">
<h2>----<span> {{ item.app_name }} </span>----</h2>
<p id="time"> Time: <span> {{item.time_stamp}} </span> </p>
<section class="flexWrap">
<div class="module" *ngFor="let subItem of item.test_cases">
<h3> {{ subItem.test_name }} </h3>
<p class="status"> {{subItem.status}} </p>
<div class="step" *ngFor = "let testStep of subItem.test_steps">
<h4>{{testStep.step_name}}</h4>
<img src="../assets/images/{{testStep.screenshot}}">
You need to import your service in app.component.ts
import { Service} from '...';
you also need implement OnInit
export class AppComponent implements OnInit
In your getData function, you have typo:
return this._http.get('./assets/data/data.json')
And the most important is you need put your service out of app.module.ts Why? Because it will create a circular dependency:
app.module.ts -> app.component.ts -> app.module.ts
Create a new service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class Service {
constructor(private _http: Http) {}
getData(){
return this._http.get('./assets/data/data.json')
.map(res => res.json());
}
}
Import it in app.module
import { Service } from './service';
Just like the first line:
import { Component } from '#angular/core';,
you need to add a line
import { Service } from X
where X is the path of the file which defines Service. I guess in your case you are defining Service in app.module, so try
import { Service } from ./app.module.ts
(if app.module.ts is in same directory, otherwise include path to that directory)

Trying to pass JSON data with angular/nativescript routing

I'm currently working on a nativescript/angular/typescript project and I'm basically trying to pass JSON data from one view (property) to another (propertyinfo).
First, I load up a JSON file in property.service.ts:
import { Injectable } from '#angular/core';
import { HttpClientModule, HttpClient } from '#angular/common/http';
#Injectable()
export class PropertyService {
public propertyData: any;
public selectedProperty: any;
constructor(private http: HttpClient) {
this.loadProperties();
}
loadProperties() {
this.http.get('/pages/property/property.json').subscribe(
(data) => {
this.propertyData = data;
}
)
}
}
This JSON data gets displayed in a view property.component.html:
<StackLayout *ngFor="let item of propertyData" class="list-group" xstyle="height: 300">
<GridLayout rows="110" columns="*, 40" (tap)="details(item)">
<StackLayout row="0" col="0">
<Label text="{{item.streetName}} {{item.houseNumber}}" class="text-primary p-l-30 p-t-5"></Label>
<Label text="{{item.etc}} {{item.etc}}" class="text-primary p-l-30 p-t-5"></Label>
</StackLayout>
<Label row="0" col="1" text="" class="fa arrow" verticalAlignment="middle"></Label>
</GridLayout>
<StackLayout class="hr-light"></StackLayout>
Here, the (tap)="details(item)" will call a function in property.component.ts:
import { Component, OnInit } from '#angular/core';
import { Router } from "#angular/router";
import { PropertyService } from './property.service';
#Component({
selector: 'app-property',
templateUrl: 'pages/property/property.component.html',
providers: [PropertyService]
})
export class PropertyComponent implements OnInit {
public propertyData: any;
constructor(private router: Router, private propertyService: PropertyService) {}
ngOnInit() {
this.propertyData = this.propertyService.propertyData;
}
details(item: any) {
this.propertyService.selectedProperty = item;
this.router.navigate(["/propertyinfo"]);
}
}
Now, when I perform a console.log(JSON.stringify(this.propertyService.selectedProperty)); within my details function, the output is as follows:
JS: {"ID":4,"description":"Lorem ipsum dolor sit amet...", "streetName":"Somestreet","houseNumber":459,"etc":"etc"}
This is my propertyinfo.component.ts:
import { Component, OnInit } from '#angular/core';
import { PropertyService } from '../property/property.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-propertyinfo',
templateUrl: 'pages/propertyinfo/propertyinfo.component.html'
})
export class PropertyinfoComponent implements OnInit {
public selectedProperty: any;
constructor(private propertyService: PropertyService, private router: Router) {
this.selectedProperty = this.propertyService.selectedProperty;
}
ngOnInit() { }
}
Yet, when I perform a console.log(JSON.stringify(this.selectedProperty)); inside the constructor, the output is JS: undefined.
At the bottom of this post, I'll add the app.routing.ts and app.module.ts files so you can see all of my imports/directives etc. I'm really at a loss as to what I'm missing. I hope you can help me.
app.routing.ts:
import { NgModule } from "#angular/core";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { Routes } from "#angular/router";
import { PropertyComponent } from "./pages/property/property.component";
import { PropertyinfoComponent } from ".//pages/propertyinfo/propertyinfo.component";
const routes: Routes = [
{ path: "", component: PropertyComponent },
{ path: "propertyinfo", component: PropertyinfoComponent },
];
#NgModule({
imports: [NativeScriptRouterModule.forRoot(routes)],
exports: [NativeScriptRouterModule]
})
export class AppRoutingModule { }
app.module.ts:
import { NgModule, NO_ERRORS_SCHEMA } from "#angular/core";
import { NativeScriptHttpClientModule } from "nativescript-angular/http-client";
import { HttpClientModule, HttpClient } from '#angular/common/http';
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
import { NativeScriptRouterModule } from "nativescript-angular/router";
import { AppRoutingModule } from "./app.routing";
import { AppComponent } from "./app.component";
import { PropertyService } from "./pages/property/property.service";
import { PropertyComponent } from "./pages/property/property.component";
import { PropertyinfoComponent } from "./pages/propertyinfo/propertyinfo.component";
#NgModule({
bootstrap: [
AppComponent
],
imports: [
NativeScriptModule,
AppRoutingModule,
NativeScriptRouterModule,
HttpClientModule,
NativeScriptHttpClientModule,
],
declarations: [
AppComponent,
PropertyComponent,
PropertyinfoComponent
],
providers: [
PropertyService
],
schemas: [
NO_ERRORS_SCHEMA
]
})
export class AppModule { }
Thank you for any help in advance. If I need to clear things up/provide any more info, please let me know.
console.log(JSON.stringify(this.selectedProperty)) returns undefined in PropertyinfoComponent because the PropertyService service being injected is not the same instance in PropertyinfoComponent than it is in PropertyComponent
you did not post the full .html for both component so I can only assume that you have something like the PropertyComponent is a parent component and has a reference/include a PropertyinfoComponent in the html and because of the way angular work, it injected a new instance of the service instead of using the one from the parent component.
check Thierry Templier answer for more information about angular service injection for this type of issue : How do I create a singleton service in Angular 2?

Can't I use a component defined in a file other than app.component.ts in HTML directly?

I am facing difficulty in using a component defined in a file named navigation.component.ts directly on HTML Page.
The same component works fine if I use it under template of a component defined on app.component.ts.
Contents of app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { NavigationComponent} from './shared/navigation.component';
#NgModule({
imports: [BrowserModule],
declarations: [AppComponent, NavigationComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Contents of navigation.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'navigation',
templateUrl: '/views/shared/navigation.html'
})
export class NavigationComponent {
userName: string = 'Anonymous';
}
Contents of app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'main-app',
template: '<navigation></navigation><h1>{{pageTitle}}</h1>'
})
export class AppComponent {
pageTitle: string = 'Portal 2.0';
}
Contents of index.html
<body>
<main-app></main-app>
</body>
The above works and renders menus on top but when I try to use <navigation> directly (given below) it doesn't render it, doesn't show any errors either.
<body>
<navigation></navigation>
</body>
Am I doing something wrong?
And the bigger question is how I go debugging issues like this?
Yes you can use web components. Add all the components that you want to load to entrycomponents.
Using createCustomElement you can create elements and use their selector anywhere.
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, Injector } from '#angular/core';
import { createCustomElement } from '#angular/elements';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
entryComponents: [AppComponent]
})
export class AppModule {
constructor(private injector: Injector) {
console.log('Elements is loaded: Activation');
this.registerComponent('metro-activation-loader', AppComponent);
}
public ngDoBootstrap(): void {
console.log('Elements is loaded: Activation ngDoBootstrap');
}
// tslint:disable-next-line:no-any
private registerComponent(name: string, component: any): void {
const injector = this.injector;
const customElement = createCustomElement(component, { injector });
customElements.define(name, customElement);
}
}