在Angular2中通信三个组件(一个父组件和两个子组件)。

14 浏览
0 Comments

在Angular2中通信三个组件(一个父组件和两个子组件)。

我正在使用Angular 2开发一个购物车。购物车中包含了两个组件(分类和产品列表),它们都在应用组件(第三个组件)中。现在的问题是我无法让这两个子组件进行通信。我尝试了以下两种解决方案:

解决方案1:我在分类组件中使用了产品组件作为提供者,一切都正常,除了在选择分类时,产品组件的视图没有更新/刷新。

解决方案2:我在共享服务中使用了"rxjs/Subject",并将选择的分类传递给产品组件,但不知道如何在选择/更改分类时调用产品组件的函数(getProducts())。非常感谢您的帮助。

0
0 Comments

在Angular2中,我们需要使用()()来实现父组件(product)和子组件(category)之间的交互。下面是一个出现这个问题的示例代码,以及解决方法。

首先,我们需要在父组件的HTML文件(product.component.html)中引入子组件,并通过[categoryResult]="categoryFilterValue"将父组件的值传递给子组件,通过(clicked)="onClickedCategoryFilter($event)"监听子组件的点击事件。

然后,在父组件的TypeScript文件(product.component.ts)中,我们需要定义一个categoryFilterValue变量,并在onClickedCategoryFilter方法中接收子组件传递的值。

接下来,我们需要在子组件的HTML文件(category.component.html)中添加代码来展示不同类型的分类。

最后,在子组件的TypeScript文件(category.component.ts)中,我们需要定义一个categoryFilterList数组来存储选中的分类,并在onClickSelectCategory方法中根据点击事件的状态判断是添加还是移除分类,并通过this.clicked.emit(this.categoryFilterList)将选中的分类传递给父组件。

通过以上步骤,我们就可以实现父组件和子组件之间的交互了。

代码如下:




// product.component.ts
import { Component, OnInit, ChangeDetectionStrategy } from '/core';
({
  moduleId: module.id,
  selector: 'all-products',
  templateUrl: 'all-products.component.html',
  changeDetection: ChangeDetectionStrategy.Default
})
export class AllProductsComponent implements OnInit {
  categoryFilterValue: any;
  constructor(private _productsService: ProductsService, private _router: Router) {}
  ngOnInit() {
    this.fillAllProducts(0);
  }
  fillAllProducts(pageIndex) {
    // TODO - service call
  }
  onClickedCategoryFilter(filterValue: any) {
    this.categoryFilterValue = filterValue;
    // TODO - update product list
  }
  selectProduct(productId: any, selectedProductCart) {
    // TODO
  }
}


// category.component.ts
import { Component, Input, Output, EventEmitter, OnInit, AfterViewInit } from '/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/debounceTime';
import { CategoriesService } from '../service/categories.service';
({
  moduleId: module.id,
  selector: 'app-filter-categories',
  templateUrl: 'category.component.html'
})
export class CategoryFilterComponent implements OnInit, AfterViewInit {
  categoryResult: any = '';
  clicked = new EventEmitter();
  categoryFilterList: any[] = [];
  constructor(private _categoriesService : CategoriesService) {}
  ngOnInit() {
    // todo - fill categories list
  }
  onClickSelectCategory(searchType: any, event: any): any {
    if (!(event.target.parentElement.className.search('active') > 1)) {
      // remove deselected data from categoryFilterList
    } else {
      this.categoryFilterList.push(element);
    }
    this.clicked.emit(this.categoryFilterList);
  }
}

以上就是解决问题的方法,希望能对你有所帮助。

0
0 Comments

在Angular2中,有一个问题涉及到了在父组件中与两个子组件之间进行通信的情况。问题的出现原因是为了展示一个示例应用程序的结构以使其正常工作。解决方法是通过使用服务和输入绑定来实现父子组件之间的通信。

首先,我们有一个CategoryComponent,它订阅CategoryService。

CategoryComponent的模板如下:

Category Component

CategoryComponent的TypeScript文件如下:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { CategoryService } from '../services/category.service';
import { Category } from '../models/models';
@Component({
    moduleId: module.id,
    selector: 'pm-category',
    templateUrl: 'category.component.html',
    styleUrls: ['category.component.scss']
})
export class CategoryComponent implements OnInit, OnDestroy {
    private categories: Array = [];
    constructor(private categoryService: CategoryService) {
    }
    ngOnInit() {
        this.categoryService.getCategories().subscribe(list => {
            if (list) {
                this.categories = list;
            }
        });
    }
    ngOnDestroy() { }
    private emitChange(): void {
        this.categoryService.setCategories(this.categories);
    }
}

每当点击一个Category时,服务就会更新。

接下来,我们有一个ProductsComponent,它订阅CategoryService和ProductsService,并包含一个子组件ProductComponent。

ProductsComponent的模板如下:

Products Component

ProductsComponent的TypeScript文件如下:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ProductsService } from '../services/products.service';
import { CategoryService } from '../services/category.service';
import { Product } from '../models/models';
@Component({
    moduleId: module.id,
    selector: 'pm-products',
    templateUrl: 'products.component.html',
    styleUrls: ['products.component.scss']
})
export class ProductsComponent implements OnInit, OnDestroy {
    public product: Product;
    private products: Array = [];
    constructor(
       private productsService: ProductsService,
       private categoryService: CategoryService
    ) { }
    ngOnInit() {
        this.productsService.getProducts().subscribe(list => {
            if (list) {
                this.products = list;
            }
        });
        this.categoryService.getCategories().subscribe(list => {
            const allProducts = this.productsService.getProductsValue();
            const filteredProducts: Array = [];
            let tempProducts: Array = [];
            list.forEach(cat => {
                tempProducts = allProducts.filter(prod => (prod.categoryId === cat.id) && (cat.selected === true));
                if (tempProducts.length > 0) {
                    tempProducts.forEach(el => {
                        filteredProducts.push(el);
                    });
                }
            });
            this.products = filteredProducts;
        });
    }
    ngOnDestroy() { }
    private setSelectedProduct(product: Product): void {
        this.product = product;
    }
}

当选择一个产品时,它的详细信息将通过输入绑定显示在ProductComponent中。当在CategoryComponent中更改一个类别时,产品列表会根据选中的复选框的选择情况而变宽或变窄。

ProductComponent的模板如下:

Product Component

Price: {{product?.details?.price}}
Age: {{product?.details?.age}}

ProductComponent的TypeScript文件如下:

import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { Product } from '../models/models';
@Component({
    moduleId: module.id,
    selector: 'pm-product',
    templateUrl: 'product.component.html',
    styleUrls: ['product.component.scss']
})
export class ProductComponent implements OnInit, OnDestroy {
    @Input() product: Product;
    ngOnInit() { }
    ngOnDestroy() { }
}

请注意,我省略了所有的sass文件,因为它们是空的。但是你必须拥有它们才能编译你的应用程序!

最后,我们有两个服务和一个模型文件models.ts。

CategoryService的代码如下:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { Category } from '../models/models';
@Injectable()
export class CategoryService {
    private categories: BehaviorSubject> = new BehaviorSubject([]);
    constructor() {
        const list: Array = [];
        const categoryA: Category = new Category('CategoryA', false);
        categoryA.id = 1000;
        list.push(categoryA);
        const categoryB: Category = new Category('CategoryB', false);
        categoryB.id = 2000;
        list.push(categoryB);
        const categoryC: Category = new Category('CategoryC', false);
        categoryC.id = 3000;
        list.push(categoryC);
        this.setCategories(list);
    }
    getCategories(): Observable> {
        return this.categories.asObservable();
    }
    getCategoriesValue(): Array {
        return this.categories.getValue();
    }
    setCategories(val: Array) {
        this.categories.next(val);
    }
}

ProductsService的代码如下:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { Product, Details } from '../models/models';
@Injectable()
export class ProductsService {
    private products: BehaviorSubject> = new BehaviorSubject([]);
    constructor() {
        const list: Array = [];
        const detailsA: Details = new Details(33, 12);
        const productA: Product = new Product('ProductA', detailsA, 1000);
        productA.id = 200;
        list.push(productA);
        const detailsB: Details = new Details(1002, 56);
        const productB: Product = new Product('ProductB', detailsB, 1000);
        productB.id = 400;
        list.push(productB);
        const detailsC: Details = new Details(9, 4);
        const productC: Product = new Product('ProductC', detailsC, 2000);
        productC.id = 600;
        list.push(productC);
        this.setProducts(list);
    }
    getProducts(): Observable> {
        return this.products.asObservable();
    }
    getProductsValue(): Array {
        return this.products.getValue();
    }
    setProducts(val: Array) {
        this.products.next(val);
    }
}

最后,我们还有一个主要的main-page.module.ts,我将它导入到app.module.ts中。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { MainPageComponent } from './main-page.component';
import { CategoryComponent } from '../category/category.component';
import { ProductComponent } from '../product/product.component';
import { ProductsComponent } from '../products/products.component';
import { CategoryService } from '../services/category.service';
import { ProductsService } from '../services/products.service';
@NgModule({
    imports: [
        FormsModule,
        BrowserModule,
        HttpClientModule,
        RouterModule.forRoot([
            { path: 'pm-main-page', component: MainPageComponent },
        ]),
    ],
    declarations: [
       MainPageComponent,
       CategoryComponent,
       ProductComponent,
       ProductsComponent
    ],
    exports: [
       MainPageComponent,
       CategoryComponent,
       ProductComponent,
       ProductsComponent
    ],
    providers: [
       CategoryService,
       ProductsService
    ]
})
export class MainPageModule {
}

将所有这些组合在一起,你将得到一个小型的工作应用程序,完全按照你在帖子中描述的方式工作。希望对你有所帮助。

0
0 Comments

在今天的问题中,用户想要在外部访问变量Output1,但是目前的代码并不能实现这个功能。下面是一个解决方案:

首先,我们定义一个output1变量,并通过setCurrentValue函数将其赋值为一个随机数。然后,通过sendNumber函数将output1的值发送到test.php文件中。接着,使用window.setInterval函数每隔1秒钟调用setCurrentValue函数,以保证output1的值始终是最新的。最后,通过一个按钮点击事件调用sendNumber函数。

如果你想在控制台中监测output1的值,可以使用monitor变量和window.setInterval函数,每隔500毫秒将output1的值打印到控制台中。

以上是我建议的解决方案,如果对你有帮助,请给我一个赞。谢谢!

用户尝试了上述解决方案,但是仍然没有实现预期的效果。用户修改了代码如下:

首先,将setCurrentValue函数和monitor函数中的output1变量名改为rngOutput1。然后,在sendNumber函数中将monitor变量的值作为参数发送到test.php文件中。最后,通过一个按钮点击事件调用sendNumber函数。

用户重新编辑了帖子,根据你的评论进行了修改。请尝试按照这种方式进行操作。请注意,monitor函数的目的是将变量的内容输出到控制台中。monitor对象返回Interval-Task的ID,只有在停止Interval时才有用。直接使用output1作为参数进行post操作,应该可以实现预期的效果。

用户回复说:“太棒了!它起作用了。非常感谢你的帮助。”

以上就是该问题出现的原因以及解决方法的整理。

0