Socrata SODA client for Angular
npm install soda-angular --saveAlso install these dev dependencies:
npm install geojson @types/geojson --save-dev- Add the
SodaClientModuleto your module imports:
import{SodaClientModule}from'soda-angular';
...
@NgModule({
...
imports: [
...
SodaClientModule.forRoot()]})exportclassAppModule{}- Create models for your dataset(s), decoated with a
@SodaDatasetthat provides the dataset id:
import{FloatingTimestamp,Location}from'soda-angular';import{SodaDataset}from'soda-angular';
@SodaDataset('8b78-2kux')exportclassDevelopmentPermit{city_file_number: string;permit_type: string;permit_class: string;permit_date: FloatingTimestamp;status: string;description_of_development: string;address: string;legal_description: string;neighbourhood_id: number;neighbourhood: string;zoning: string;location: Location;}
@SodaDataset('rwuh-apwg')exportclassBuildingPermit{row_id: string;permit_number: string;permit_date: FloatingTimestamp;address: string;legal_description: string;neighbourhood: string;job_description: string;building_type: string;construction_value: number;zoning: string;location: Location;}
@SodaDataset('kk4c-7pcv')exportclassLegalParcel{id: number;latitude: number;longitude: number;area: number;geometry: MultiPolygon;}- Extend
SodaContextwith your own service context. Provide the URL to the Socrata service of your choice via the@SodaHostdecorator, and create yourSodaResourceobjects with a dataset models:
import{Injectable}from'@angular/core';import{SodaClient,SodaContext,SodaHost,SodaResource}from'soda-angular';
@Injectable({providedIn: 'root',})
@SodaHost('https://data.edmonton.ca/')exportclassOdpContextextendsSodaContext{publicreadonlydevelopmentPermits: SodaResource<DevelopmentPermit>;publicreadonlybuildingPermits: SodaResource<BuildingPermit>;constructor(sodaClient: SodaClient){super(sodaClient);this.developmentPermits=newSodaResource(DevelopmentPermit,this);this.buildingPermits=newSodaResource(BuildingPermit,this);}}- Inject your Context into your component, and query against it using fluent querying:
import{Component,OnInit}from'@angular/core';import{FloatingTimestamp,Location}from'soda-angular';
@Component({selector: 'permits',templateUrl: './permits.component.html',styleUrls: ['./permits.component.css']})exportclassPermitsComponentimplementsOnInit{publicDevelopmentPermits: DevelopmentPermit[];publicBuildingPermits: BuildingPermit[];constructor(privatecontext: OdpContext){}ngOnInit(){this.context.developmentPermits.where(p=>p.permit_type).equals('Major Development Permit').and(p=>p.permit_date).greaterThan(newFloatingTimestamp('04/23/2020 GMT')).and(p=>p.zoning).not().equals('RF1').orderBy(p=>neighbourhood).observable().subscribe(permits=>this.DevelopmentPermits=permits);this.context.buildingPermits.where(p=>p.permit_date).greaterThan(newFloatingTimestamp('04/23/2020 GMT')).and(p=>p.neighbourhood).equals('DOWNTOWN').or(p=>p.neighbourhood).equals('OLIVER').observable().subscribe(permits=>this.BuildingPermits=permits);}}this.context.developmentPermits.location(p=>p.location).withinCircle(newLocation(53.540959,-113.493819),2000));this.context.buildingPermits.location(p=>p.location).withinBox(newLocation(46.883198,-96.798216),newLocation(46.873169,-96.785139)));import{MultiPolygon,Point}from'geojson';import{GeoJSONUtils}from'soda-angular';this.context.legalParcels.geomery(p=>p.geometry).intersects(GeoJSONUtils.point(-71.099290,-31.518292));this.context.legalParcels.geomery(p=>p.geometry).intersects(GeoJSONUtils.polygon([-113.599831726514,53.458273089013],[-113.600049996812,53.45827360864],[-113.600052949158,53.457932503403],[-113.599845224387,53.457931995732],[-113.599834691275,53.457931970341],[-113.599831726514,53.458273089013]));this.context.legalParcels.geomery(p=>p.latlon).withinPolygon(GeoJSONUtils.multipolygon([[-113.599831726514,53.458273089013],[-113.600049996812,53.45827360864],[-113.600052949158,53.457932503403],[-113.599845224387,53.457931995732],[-113.599834691275,53.457931970341],[-113.599831726514,53.458273089013]]));You can also use query builders for more control (including OR queries):
constbuilder=newSoqlQueryBuilder();.filter(newWhereFilter(newColumn('permit_type'),Comparitor.Equals,newWhereValue('Major Development Permit'),),newWhereOperator(Operator.And),newWhereGroup(newWhereFilter(newColumn('permit_value'),Comparitor.GreaterThan,newWhereValue(2000000),),newWhereOperator(Operator.Or),newWhereGroup(newWhereFilter(newColumn('permit_class'),Comparitor.Equals,newWhereValue('Class B'),)))).offset(20).limit(20).orderBy(newColumn('neighbourhood'));this.context.developmentPermits.get(builder.getQuery()).subscribe(permits=>this.Permits=permits);- This is a work in progress, watch this repository for updates.
- Heavily inspired by Entity Framework.
- Filter grouping coming soon.
- Support for case-insensitive text matches is coming.
- Support for select-based functions are coming.
- Socrata Developers
- yeg-dev-dashboard (Example project)
See LICENSE.