Error:error Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays - angular4-httpclient

I am trying to bind some JSON data from my API to HTML and iterate it over it using *ngFor in angular 4. Unfortunately, I'm getting the error in this question's title.
The code in question:
countryList.ts
export interface CountryList {
UserName : string,
Country : string[],
}
Service.ts
export class LoginServicesService {
constructor(private o:Http) { }
functionCountriesList(userName:string)
{
return this.o.get('http://localhost:55760/api/Login/GetCountries/'+userName).map((res:Response) =><CountryList[]>res.json());
}
}
Component.ts
export class LoginComponent implements OnInit {
constructor(private loginService: LoginServicesService) { }
ngOnInit() {
}
countries: CountryList[];
countryValue: number;
countryName: string;
GenerateCountries(userName: string) {
this.loginService.functionCountriesList(userName).subscribe((data) => this.countries = data);
console.log(this.countries);
}
}
Component.HTML
<table align="center">
<tr>
<td><label id="lblUserName">UserName:</label></td>
<td><input #userName type="Textbox" id="txtUserName" (keyup.enter)="GenerateCountries(userName.value)" (blur)="GenerateCountries(userName.value)" /></td>
</tr>
<tr>
<td>
<label id="lblPassword">Password:</label>
</td>
<td><input type="password" id="txtPassword"/></td>
</tr>
<tr>
<td>Domain:</td>
<td>
<select id= "district" style="width:100%" (change)="selectdrop($event)">
<option value="NIL">Select Domain</option>
<option *ngFor="let c of countries;let i=index">{{c}}</option>
</select>
</td>
</tr>
</table>
JSON from api is
{
"UserName": "hello",
"Country": [
"South Africa",
"Russia",
"India",
"America",
]
}

Your problem is that you're trying to directly iterate through the result of your API call, which a JSON object as you've pasted. You need to sub-select the "Country" field from your API response first and iterate through that.

Related

How to add "handleRemove" function to Graphql both Query and Delete Mutation?

My Application is using React, Apollo client 2, Apollo Server and MongoDB as the database.
I try to add "handleRemove" function to query page that I use React.
But when I click "Delete" button, I get "deleteCustomer" is not the function.
Here is my code of this page, please help to find out the solution.
import React, { Component } from 'react';
import gql from 'graphql-tag';
import { graphql, compose } from 'react-apollo';
import { Link } from 'react-router-dom';
import { Button, Alert } from 'react-bootstrap';
import Loading from '../components/Loading';
class Customers extends Component {
handleRemove = async (customerID) => {
const result = await this.props.deleteCustomer({
variables: {
_id: customerID,
},
})
}
render() {
const { data: {loading, CustomersList }, match, history } = this.props;
return ( !loading ? (
<div className="Customers">
<h2><p className="text-center">Customer List</p></h2>
<Button><Link to={`/customers/new`}>Add Customer</Link></Button>
<br />
<br />
{CustomersList.length ?
<table className="zui-table zui-table-rounded">
<thead>
<tr>
<th><p className="text-center">List</p></th>
<th>
</th>
<th><p className="text-center">Salution</p></th>
<th><p className="text-center">Firstname</p></th>
<th><p className="text-center">Lastname</p></th>
<th><p className="text-center">Nickname</p></th>
<th><p className="text-center">Email</p></th>
<th><p className="text-center">Phone</p></th>
<th><p className="text-center">Mobile</p></th>
<th />
<th />
</tr>
</thead>
<tbody>
{CustomersList.map(({ _id, salution, firstname, lastname, nickname, email, phone, mobile, total_spent, createdAt, updatedAt }, index) => (
<tr key={_id}>
<td>{index+1}</td>
<td>
</td>
<td>{salution}</td>
<td>{firstname}</td>
<td>{lastname}</td>
<td>{nickname}</td>
<td>{email}</td>
<td>{phone}</td>
<td>{mobile}</td>
<td>
<p className="text-center">
<button className="btn btn-info btn-sm"
onClick={() => history.push(`${match.url}/${_id}/edit`)}
>Edit</button>
</p>
</td>
<td>
<p className="text-center">
<button className="btn btn-danger btn-sm"
onClick={() => this.handleRemove(_id)}
>Delete</button>
</p>
</td>
</tr>
))}
</tbody>
</table> : <Alert bsStyle="warning">Nobody registered yet!</Alert>}
</div>
) : <Loading /> );
}
}
export const customersListQuery = gql`
query customersListQuery {
CustomersList {
_id
salution
firstname
lastname
nickname
email
phone
mobile
total_spent
createdAt
updatedAt
}
}
`;
export const deleteCustomer = gql`
mutation deleteCustomer($_id: ID!) {
deleteCustomer(_id: $_id) {
_id
}
}
`;
export default compose(
graphql(customersListQuery),
graphql(deleteCustomer, { name: deleteCustomer }),
)(Customers);
The name of the mutation should be a string. The quotes are missing:
...
export default compose(
graphql(customersListQuery),
graphql(deleteCustomer, { name: "deleteCustomer" }),
)(Customers);

Angular2 Reactive Form Table

I am having some trouble looking up and attempting to do what I want to.
I have a table with inputs in each row, and I want each row which is created using an ngFor, to be considered a form group.
Within each form group I want a validation in that if any of the controls are filled within the row, that the entire form group needs to be filled before submission can be done.
Here is what I have so far in my template.
I don't have anything in the component yet as Angular.io and searching around for a few hours has not shown me anything close to what I want.
<form>
<table id="table" class="mdl-data-table mdl-js-data-table mdl-data-table mdl-shadow--2dp">
<thead>
<tr>
<th>Day</th>
<th>Description</th>
<th>Open Time</th>
<th>Close Time</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let scheduleDetail of scheduleDetails">
<td style="padding: 0 8px 0 8px;">{{weekdayConverter(scheduleDetail.dayId)}}</td>
<td class="pad-input">
<mdl-textfield style="max-width:100px;" type="text" class="font" name="description" [(ngModel)]="scheduleDetail.description"></mdl-textfield>
</td>
<td>
<mdl-textfield style="max-width:75px" type="text" error-msg="hh:mm" name="openTime" pattern="([01]\d|2[0-3]):?([0-5]\d)" [(ngModel)]="scheduleDetail.openTime"></mdl-textfield>
</td>
<td>
<mdl-textfield style="max-width:75px" type="text" error-msg="hh:mm" name="closeTime" pattern="([01]\d|2[0-3]):?([0-5]\d)" [(ngModel)]="scheduleDetail.closeTime"></mdl-textfield>
</td>
</tr>
</tbody>
</table>
</form>
Update
Added the following to the template:
Changed inputs to:
<mdl-textfield (keyup)="formChange(scheduleDetail)" style="max-width:100px;" type="text" class="font" name="description" [(ngModel)]="scheduleDetail.description"></mdl-textfield>
Added the following to the component:
formChange(detail:scheduleDetail){
if(this.checkValid(detail)==false)
this.scheduleDetails.filter(detail => detail == detail)[0].require=true;
else
this.scheduleDetails.filter(detail => detail == detail)[0].require=false;
this.checkForm();
}
checkValid(detail:scheduleDetail){
if(detail.description!=null && detail.description!=""){
if(this.checkTime(detail))
return true
else
return false
}
else
return true
}
checkTime(detail:scheduleDetail){
if(
(detail.openTime!=null && detail.closeTime!=null) &&
( detail.openTime!="" && detail.closeTime!="") &&
(this.checkRegExp(detail.openTime) && this.checkRegExp(detail.closeTime))
){
return true
}
else if((this.checkRegExp(detail.openTime) && this.checkRegExp(detail.closeTime))){
return true
}
else return false
}
checkRegExp(time:string){
let timeRegExp = /([01]\d|2[0-3]):?([0-5]\d)/;
if(timeRegExp.test(time)){
return true;
}
else
return false;
}
checkForm(){
let valid: boolean = true;
this.scheduleDetails.forEach(detail => {
if(detail.require==true){
valid = false;
}
});
this.scheduleDetails.forEach(detail => {
if(detail.description=="" || detail.description==null){
valid = false;
}
});
this.formValid = valid;
}
Model Driven Forms
You are using a template driven form, which is hard to scale, and maintain.
Here, i will guide you to migrate to a model driven form.
Component
export class WeekScheduleComponent {
// Our empty Form
myForm: FormGroup;
constructor(private fb: FormBuilder){
// We inject FormBuilder to our component
// Now, we instantiate myForm with FormBuilder
// Notice that myForm is a FormGroup which contains an empty FormArray
this.myForm = this.fb.group({
scheduleDetail: this.fb.array([])
})
}
addRow(){
// This function instantiates a FormGroup for each day
// and pushes it to our FormArray
// We get our FormArray
const control = <FormArray>this.myForm.controls['scheduleDetail'];
// instantiate a new day FormGroup;
newDayGroup: FormGroup = this.initItems();
// Add it to our formArray
control.push(newDayGroup);
}
initItems(): FormGroup{
// Here, we make the form for each day
return this.fb.group({
description: [null, Validators.required],
openTime: [null, Validators.required],
closeTime: [null, Validators.required]
});
}
submit(){
// do stuff and submit result
console.log(this.myForm.value);
}
}
in your template:
<form [formGroup]="myForm" *ngIf="myForm">
<table formArrayName="scheduleDetail">
<tr *ngFor="let item of myForm.controls.scheduleDetail.controls; let i=index"
[formGroupName]="i" >
<td><input type='text' formControlName="description"></td>
<td><input type='text' formControlName="openTime"></td>
<td><input type='text' formControlName="closeTime"></td>
</tr>
</table>
</form>
<button (click)="addRow()">Add new item</button>
<button (click)="submit()" [disabled]="!myForm.valid">Submit</button>
Component
import { Component, OnInit } from '#angular/core';
import {FormGroup, FormBuilder, FormControl, Validators, FormArray} from '#angular/forms';
#Component({
selector: 'app-sales',
templateUrl: './sales.component.html',
styleUrls: ['./sales.component.css']
})
export class SalesComponent implements OnInit {
myForm: FormGroup;
constructor(private fb: FormBuilder){
}
// getter to get a reference to scheduleDetail form array in myForm form group
get scheduleDetail():FormArray{
return <FormArray>this.myForm.get('scheduleDetail')
}
// add a new row, get reference to form array using getter method and push form group into it
addRow(){
this.scheduleDetail.push(this.initItems());
}
// make a form for each row!
initItems(): FormGroup{
return this.fb.group({
description: [null, Validators.required],
openTime: [null, Validators.required],
closeTime: [null, Validators.required]
});
}
submit(){
console.log(this.myForm.value)
}
ngOnInit() {
this.myForm = this.fb.group({
scheduleDetail: this.fb.array([this.initItems()])
})
}
}
Template
<form [formGroup]="myForm" *ngIf="myForm">
<table formArrayName="scheduleDetail">
<thead>
<tr>
<th >Desc</th>
<th >Open Time</th>
<th >Close Time</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of myForm.controls.scheduleDetail.controls; let i=index"
[formGroupName]="i" >
<td><input type='text' formControlName="description"></td>
<td><input type='text' formControlName="openTime"></td>
<td><input type='text' formControlName="closeTime"></td>
</tr>
</tbody>
</table>
</form>
<button (click)="addRow()">Add new item</button>
<button (click)="submit()" [disabled]="!myForm.valid">Submit</button>

knockout update unit price when product combo changes

I have this table bounded to knockout like this
<tbody data-bind="foreach: Items">
<tr class="gradeA">
<td>
<select name="MaterialId" data-bind="options: $parent.lookups.materials, optionsText: 'Name', value: Material"></select></td>
<td>
<input type="text" name="Quantity" data-bind="value: Quantity"></td>
<td>
<input type="text" name="UnitPrice" data-bind="value: UnitPrice"></td>
<td>
<input type="text" name="Discount" data-bind="value: Discount"></td>
<td>
<input type="text" readonly="readonly" data-bind="value: Price" />
</td>
</tr>
</tbody>
javascript is:
function Item() {
this.Material = ko.observable()
this.Quantity = ko.observable(1)
this.UnitPrice = ko.observable(0)
this.Discount = ko.observable(0)
this.MaterialRetailPrice = ko.computed(function () {
return this.Material() ? this.Material().RetailPrice : 0
}, this);
this.StoreId = ko.computed(function () {
return this.Store() ? this.Store().Id : 0
}, this)
this.Price = ko.computed(function () {
return this.Quantity() * this.UnitPrice() - this.Discount()
}, this)
}
function materialBuyBillViewModel() {
var self = this
self.lookups = {
stores: ko.observableArray([]),
materials: ko.observableArray([])
}
self.Items = ko.observableArray()
self.VendorBill = ko.observable()
self.Vendor = ko.observable()
self.Discount = ko.observable()
self.Vat = ko.observable()
//... Methods to fill lookups
}
$(document).ajaxStop(function (event, request, settings) {
MaterialBuyBillViewModel.AddItem()
})
$(document).ready(function () {
MaterialBuyBillViewModel = new materialBuyBillViewModel()
})
The result is fine and I can change the unit price and get price updated, but the missing thing is to get unit price changed and price updated when product select is changed (replace unitprice value with Material().RetailPrice). any one can point me how to bind unit price input properly?
I hope I got your question correctly.
You can create a ko.computed with a read and write method.
The read method enables you to check if a material is selected. If there is, you return the price of the selected material. If there isn't, you return the user defined UnitPrice value.
The write method just forwards the user input straight to the UnitPrice property. To indicate that, when a material is selected, the user cannot define the value, I've added a disabled binding on the input field.
Let me know if this solves your problem.
function Item() {
this.Material = ko.observable();
this.Quantity = ko.observable(5);
this.UnitPrice = ko.observable(1);
this.Discount = ko.observable(0);
this.ComputedUnitPrice = ko.computed({
read: function() {
return this.Material() ? this.Material().RetailPrice : this.UnitPrice();
},
write: function(val) {
this.UnitPrice(val);
},
owner: this
});
this.Price = ko.computed(function() {
return this.Quantity() * this.ComputedUnitPrice() - this.Discount()
}, this);
}
function materialBuyBillViewModel() {
var self = this;
self.lookups = {
materials: ko.observableArray([{
Name: "Material 1",
RetailPrice: 1
}, {
Name: "Material 2",
RetailPrice: 2
}, {
Name: "Material 3",
RetailPrice: 3
}])
};
self.Items = ko.observableArray([
new Item()
]);
};
ko.applyBindings(new materialBuyBillViewModel());
[disabled] {
background: #efefef
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
<thead>
<tr>
<th>Material</th>
<th>Quantity</th>
<th>UnitPrice</th>
<th>Discount</th>
<th>Price</th>
</tr>
</thead>
<tbody data-bind="foreach: Items">
<tr class="gradeA">
<td>
<select name="MaterialId" data-bind="options: $parent.lookups.materials, optionsText: 'Name', optionsCaption: 'Pick a material', value: Material, allowValueUnset: true"></select>
</td>
<td>
<input type="text" name="Quantity" data-bind="value: Quantity">
</td>
<td>
<input type="text" name="UnitPrice" data-bind="value: ComputedUnitPrice, disable: Material">
</td>
<td>
<input type="text" name="Discount" data-bind="value: Discount">
</td>
<td>
<input type="text" readonly="readonly" data-bind="value: Price" />
</td>
</tr>
</tbody>
</table>

Update form in meteor using autoform

I have a collection that handles default values for forms. I need to build a UI to update the default values themselves, instead of force updating via mongo backed.
I've used aldeed's update-each functionality. The data is being fetched from the DB and displayed in the table. However, when I try to update by inputting new values in the textbox, it does not persist. In fact, it keeps throwing this error which i'm not aware of.
Exception in template helper: TypeError: Cannot read property 'namedContext' of undefined
at Object.autoFormFieldIsInvalid
As a sample, here is what I'm working with:
Mongo Collection:
meteor:PRIMARY> db.testCollection.find()
{ "_id" : ObjectId("577ccd87f57f43d790c3ec49"), "schemaName" : "test_schema", "label" : "test_lable", "value" : "test_value" }
Schema:
test_schema = new SimpleSchema({
"schemaName": {
type: String,
},
"label": {
type: String,
},
"value": {
type: String,
}
});
testCollection.attachSchema(test_schema);
Template:
<template name = "testTemplate">
<table class="table table-bordered table-condensed">
<thead>
<tr>
<td style="width: 85px">Schema Name</td>
<td style="width: 85px">Label</td>
<td>Default Value</td>
<td style="width: 250px">New Default Value</td>
</tr>
</thead>
<tbody>
{{#each items}}
<tr>
<td>{{this.schemaName}}</td>
<td>{{this.label}}</td>
<td>{{this.value}}</td>
<td>
{{#autoForm id=updateDefaiultsID type="update" collection=testCollection doc=this autosave=true}}
{{> afFormGroup name="value" label=false}}
{{/autoForm}}
</td>
</tr>
{{/each}}
</tbody>
</table>
</template>
Helper
import { Template } from 'meteor/templating';
import '../templates/testTemplate.html';
if (Meteor.isServer) {
Meteor.publish(null, function () {
return testCollection.find();
});
testCollection.allow({
update: function () {
return true;
}
});
}
else if (Meteor.isClient) {
Template["testTemplate"].helpers({
items: function () {
return testCollection.find({}, {sort: {name: 1}});
},
updateDefaiultsID: function () {
return "testTemplate" + this._id;
}
});
}
Change this
from
<td>{{this.schemaName}}</td>
to
<td>{{this.schema_name}}</td>

Select field in grails workflow

I have a problem prefilling a dropdown list in an grails webflow
I have a controller for the webflow
class ClearanceRequestController {
def index() {
redirect(action: "start")
}
def startFlow = {
contact {
on('next') {
flow.developer = params.developer
flow.project = params.project
flow.projectResponsible = params.projectResponsible
flow.email = params.email
[flow : flow]
}.to('application')
on('cancel').to('finish')
...
and the view looks like this:
contact.gsp
<g:if test="${message}">
<div class="message">${message}</div>
</g:if>
<g:form action="start" method="post">
<div class="dialog">
<table>
<tbody>
<tr class="prop">
<td valign="top" class="name">
<label for="projectName">Projekt:</label>
</td>
<td valign="top">
<input type="text" id="projectName" name="project" value="${params.project}" />
</td>
</tr>
<g:select name="state" from="${Project?.DIVISION_OPTIONS}" value="${Project?.DIVISION_OPTIONS}"/>
This is the Project definition
class Project {
static DIVISION_OPTIONS = ["A", "B", "C", "D"]
String name
String division
String toString(){
"$name"
}
static constraints = {
name(unique: true)
division(inList: DIVISION_OPTIONS)
}
}
I don't know how to get the data from the constraints. I tried to access
Project.constraints.division.inList
or
Project.DIVISION_OPTIONS
but both didn't worked. I assume I have to initialize the Project somewhere and pass it to the contact.gsp, but I don't know how.
OK I got it, just import the Project in the page, like
<%# page import="com.companyName.Project" contentType="text/html;charset=UTF-8" %>
or like:
<g:select name="state" from="${com.companyName.Project?.DIVISION_OPTIONS}" value="${com.companyName.Project?.DIVISION_OPTIONS}"/>