diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 8a8f854d99..42a66fa3e1 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -160,6 +160,7 @@ import { SearchSelectOntologyComponent } from './workspace/search/advanced-searc
import { ExpertSearchComponent } from './workspace/search/expert-search/expert-search.component';
import { FulltextSearchComponent } from './workspace/search/fulltext-search/fulltext-search.component';
import { SearchPanelComponent } from './workspace/search/search-panel/search-panel.component';
+import { SearchResourceComponent } from './workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component';
// translate: AoT requires an exported function for factories
export function httpLoaderFactory(httpClient: HttpClient) {
@@ -310,6 +311,7 @@ export function httpLoaderFactory(httpClient: HttpClient) {
UsersComponent,
UsersListComponent,
VisualizerComponent,
+ SearchResourceComponent,
],
imports: [
AngularSplitModule.forRoot(),
diff --git a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.html b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.html
new file mode 100644
index 0000000000..15ba0c034b
--- /dev/null
+++ b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.html
@@ -0,0 +1,7 @@
+
+
diff --git a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.scss b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.spec.ts b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.spec.ts
new file mode 100644
index 0000000000..92c4bdb802
--- /dev/null
+++ b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.spec.ts
@@ -0,0 +1,122 @@
+import { Component, Inject, Input, OnInit, ViewChild } from '@angular/core';
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { MockOntology, ResourcePropertyDefinition } from '@dasch-swiss/dsp-js';
+import { ComparisonOperatorAndValue, GreaterThan, LinkedResource, PropertyWithValue, ValueLiteral } from '../operator';
+import { SearchResourceComponent } from './search-resource.component';
+
+/**
+ * test host component to simulate parent component.
+ */
+@Component({
+ template: `
+ `
+})
+class TestHostComponent implements OnInit {
+
+ @ViewChild('searchRes', { static: false }) searchResource: SearchResourceComponent;
+
+ form;
+
+ resClass: string;
+
+ constructor(@Inject(FormBuilder) private _fb: FormBuilder) {
+ }
+
+ ngOnInit() {
+ this.form = this._fb.group({});
+ this.resClass = 'http://0.0.0.0:3333/ontology/0001/anything/v2#Thing';
+ }
+}
+
+/**
+ * test component to simulate ResourceAndPropertySelectionComponent.
+ */
+@Component({
+ selector: 'app-resource-and-property-selection',
+ template: ''
+})
+class TestResourceAndPropertySelectionComponent implements OnInit {
+
+ @Input() formGroup: FormGroup;
+
+ @Input() activeOntology: string;
+
+ @Input() resourceClassRestriction?: string;
+
+ @Input() topLevel;
+
+ // mock ref to child comp.
+ resourceClassComponent = {
+ selectedResourceClassIri: 'http://0.0.0.0:3333/ontology/0001/anything/v2#Thing'
+ };
+
+ // mock ref to child comp.
+ propertyComponents = [];
+
+ ngOnInit() {
+
+ const anythingOnto = MockOntology.mockReadOntology('http://0.0.0.0:3333/ontology/0001/anything/v2');
+
+ const linkedResValue = new ComparisonOperatorAndValue(new GreaterThan(), new ValueLiteral('0.5', 'http://www.w3.org/2001/XMLSchema#decimal'));
+
+ const hasDecimal = anythingOnto.properties['http://0.0.0.0:3333/ontology/0001/anything/v2#hasDecimal'];
+
+ const linkedResourceWithVal = new PropertyWithValue(hasDecimal as ResourcePropertyDefinition, linkedResValue, false);
+
+ this.propertyComponents = [{
+ getPropertySelectedWithValue: () => linkedResourceWithVal
+ }];
+ }
+}
+
+describe('SearchResourceComponent', () => {
+ let testHostComponent: TestHostComponent;
+ let testHostFixture: ComponentFixture;
+
+ beforeEach(waitForAsync(() => {
+
+ TestBed.configureTestingModule({
+ imports: [
+ BrowserAnimationsModule,
+ ReactiveFormsModule
+ ],
+ declarations: [
+ SearchResourceComponent,
+ TestResourceAndPropertySelectionComponent,
+ TestHostComponent
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ testHostFixture = TestBed.createComponent(TestHostComponent);
+ testHostComponent = testHostFixture.componentInstance;
+
+ testHostFixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(testHostComponent).toBeTruthy();
+ expect(testHostComponent.searchResource).toBeTruthy();
+ });
+
+ it('should correctly determine the ontology from the resource class constraint', () => {
+ expect(testHostComponent.searchResource.restrictResourceClass).toEqual('http://0.0.0.0:3333/ontology/0001/anything/v2#Thing');
+ });
+
+ it('should return a specified resource', () => {
+
+ const linkedRes = testHostComponent.searchResource.getValue();
+
+ expect(linkedRes instanceof LinkedResource).toBeTrue();
+ expect((linkedRes as LinkedResource).resourceClass).toEqual('http://0.0.0.0:3333/ontology/0001/anything/v2#Thing');
+ expect((linkedRes as LinkedResource).properties.length).toEqual(1);
+
+ expect((linkedRes as LinkedResource).properties[0].property.id).toEqual('http://0.0.0.0:3333/ontology/0001/anything/v2#hasDecimal');
+
+ });
+
+});
diff --git a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.ts b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.ts
new file mode 100644
index 0000000000..603d60d503
--- /dev/null
+++ b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.ts
@@ -0,0 +1,63 @@
+import { Component, Inject, Input, OnInit, ViewChild } from '@angular/core';
+import { FormBuilder, FormGroup } from '@angular/forms';
+import { Constants } from '@dasch-swiss/dsp-js';
+import { ResourceAndPropertySelectionComponent } from '../../../resource-and-property-selection.component';
+import { LinkedResource, PropertyValue, PropertyWithValue, Value } from '../operator';
+
+// https://stackoverflow.com/questions/45661010/dynamic-nested-reactive-form-expressionchangedafterithasbeencheckederror
+const resolvedPromise = Promise.resolve(null);
+
+@Component({
+ selector: 'app-search-resource',
+ templateUrl: './search-resource.component.html',
+ styleUrls: ['./search-resource.component.scss']
+})
+export class SearchResourceComponent implements OnInit, PropertyValue {
+
+ // parent FormGroup
+ @Input() formGroup: FormGroup;
+
+ @Input() restrictResourceClass: string;
+
+ // reference to the component that controls the resource class selection
+ @ViewChild('resAndPropSel') resourceAndPropertySelection: ResourceAndPropertySelectionComponent;
+
+ type = Constants.Resource;
+
+ form: FormGroup;
+
+ ontology: string;
+
+ constructor(@Inject(FormBuilder) private _fb: FormBuilder) {
+ }
+
+ ngOnInit(): void {
+
+ this.form = this._fb.group({});
+
+ resolvedPromise.then(() => {
+ this.formGroup.addControl('propValue', this.form);
+ });
+
+ // get ontology from restriction
+ this.ontology = this.restrictResourceClass.split('#')[0];
+ }
+
+ getValue(): Value {
+
+ const resClassOption = this.resourceAndPropertySelection.resourceClassComponent.selectedResourceClassIri;
+
+ let resClass;
+
+ if (resClassOption !== false) {
+ resClass = resClassOption;
+ }
+
+ const properties: PropertyWithValue[] = this.resourceAndPropertySelection.propertyComponents.map(
+ (propComp) => propComp.getPropertySelectedWithValue()
+ );
+
+ return new LinkedResource(properties, resClass);
+ }
+
+}
diff --git a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/specify-property-value.component.html b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/specify-property-value.component.html
index 79d80a5407..d47352febb 100644
--- a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/specify-property-value.component.html
+++ b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/specify-property-value.component.html
@@ -7,8 +7,8 @@
-
+
@@ -16,7 +16,7 @@
-
+