How to clean from the values? - laravel

I'm using a laravel-vue-boilerplate .In the package there is User CRUD. I made a same thing,copy/paste,change couple of details to have Item CRUD.Working fine. The issue is after action (edit) I want to add a new Item,the form is filled already with the edited Item values. The form is in a modal which is a component.
Don't know which part of the code I paste here,Looking forward!
Modal :
addItem(): void {//this is the actions to call the modal
this.isModalAdd = true;
this.setModalVisible(true);
this.form=this.new_form;
}
edit(item:Item):void{
this.isModalAdd = false;
this.setModalVisible(true);
this.form = { ...item };
}
<ItemsModal v-bind:form='form' v-bind:is-add='isModalAdd' v-bind:is-visible='isModalVisible' ></ItemsModal>//added in the Items template
<script lang="ts">//Items Modal
import { Component, Emit, Prop, Vue } from 'vue-property-decorator';
import { Action, State, namespace } from 'vuex-class';
import checkPassword from '#/utils/checkPassword';
const iStore = namespace('items');
#Component
export default class ItemsModal extends Vue {
#Prop() form;
#Prop() isAdd;
#Prop() isVisible;
#iStore.Action addItem;
#iStore.Action editItem;
#iStore.Action setModalVisible;
#iStore.State isModalLoading;
handleOk() {
if (this.isAdd) {
this.addItem(this.form);
} else {
this.editItem(this.form);
}
}
handleClose() {
this.setModalVisible(false);
}
}
</script>
<template lang="pug">
b-modal(
hide-header-close=true,
:visible='isVisible',
:cancel-title='$t("buttons.cancel")',
:ok-disabled='isModalLoading',
:ok-title='isModalLoading ? $t("buttons.sending") : isAdd ? $t("buttons.add") : $t("buttons.update")',
:title='isAdd ? $t("users.add_user") : $t("users.edit_user")',
#hide='handleClose',
#ok.prevent='handleOk',
)
b-form
b-form-group(
:label='$t("strings.name")'
label-for='name',
)
b-form-input#name(
type='text',
v-model='form.name',
maxlength='191',
required,
)
</template>

Your code seems incomplete to me. As per my guess, after your form submit, you should empty your form data. Means, at the end of addItem(this.form), this.editItem(this.form), setModalVisible(false) these methods, You should empty your this.form data or nullified form's properties. Like,
this.form = {}
or
this.form.name = null
After completing action from your api, try to empty or null your Datas related to that form.
editItem (form) {
// work with your backend
this.form = {}
}

Related

Sending data to a server using remix run

I am having issues sending data to a server using remix run - I'm not sure I fully understand how useAction data works. I understand how the useLoaderData functions work but when you are trying to send data to a server I get errors.
What I want to do is send a post request to my server when I click a button - if I try and call create cart in the handleCLick event it says that createCart is not a function when it is
const submit = useSubmit()
function action({ request }) {
is this where i do my POST api call?
}
async function handleClick(event) {
await createCart(id, amount)
}
Cant seem to find any documentation which tells you how to do this?
EDIT: Hit send too early
With Remix, actions always run on the server. It is the method that Remix will call when you POST to a route.
// route.tsx
import { json, type ActionArgs, type LoaderArgs } from '#remix-run/node'
import { Form, useActionData, useLoaderData, useSubmit } from '#remix-run/react'
import { createCart } from '~/models/cart.server' // your app code
import { getUserId } from '~/models/user.server'
// loader is called on GET
export const loader = async ({request}: LoaderArgs) => {
// get current user id
const id = await getUserId(request)
// return
return json({ id })
}
// action is called on POST
export const action = async ({request}: ActionArgs) => {
// get the form data from the POST
const formData = await request.formData()
// get the values from form data converting types
const id = Number(formData.get('id'))
const amount = Number(formData.get('amount'))
// call function on back end to create cart
const cart = await createCart(id, amount)
// return the cart to the client
return json({ cart })
}
// this is your UI component
export default function Cart() {
// useLoaderData is simply returning the data from loader, it has already
// been fetched before component is rendered. It does NOT do the actual
// fetch, Remix fetches for you
const { id } = useLoaderData<typeof loader>()
// useActionData returns result from action (it's undefined until
// action has been called so guard against that for destructuring
const { cart } = useActionData<typeof action>() ?? {}
// Remix handles Form submit automatically so you don't really
// need the useSubmit hook
const submit = useSubmit()
const handleSubmit = (e) => {
submit(e.target.form)
}
return (
<Form method="post">
{/* hidden form field to pass back user id *}
<input type="hidden" name="id"/>
<input type="number" name="amount"/>
{/* Remix will automatically call submit when you click button *}
<button>Create Cart</button>
{/* show returned cart data from action */}
<pre>{JSON.stringify(cart, null, 2)}</pre>
</Form>
)
}

How to filter through content of component with a string passed through the props?

With a text field in the parent component, I want to filter through multiple child components where the string is being passed through the props. The child components have been outputted through a map function which is importing data from an API into the props also. I have the user input console logging after being passed as props to the child (searchTerm). My problem is that I can't hide the display of individual components based on the user's input. The trouble I'm having is that when one decides to hide itself - they all do. I've tried indexOf and have found include() to be more useful. I'm worried about my approach to the problem and would appreciate some wisdom from more seasoned react developers.
//parent component
render() {
return (
<React.Fragment>
<input type="text" className = {styles.searchField} id="searchField" placeholder = "Search..." onChange = {this.getUserInput}/>
<div className={styles.container}>
{this.state.importedBooks.map((element, index) => (
<Tile key ={index} searchTerm ={this.state.searchTerm} buy ={element.amazon_product_url}
img ={element.book_image} summary ={element.description} url={element.book_image}
book_author ={element.author} book_title ={element.title} />
))}
</div>
</React.Fragment>);
}
}
//child component
class Tile extends React.Component {
public state:{display:boolean} = {display:true};
public getContainerContent = () => {
const containers: NodeListOf<Element> | null = document.querySelectorAll("#container");
containers.forEach(element => {
if (element.innerHTML.toLocaleLowerCase().includes(this.props.searchTerm) !== false) {
this.setState({display:true});
}
else if (this.props.searchTerm == "") {
this.setState({display:true});
}
else {
this.setState({ display: false });
}
})
};
public componentWillReceiveProps = () => {
this.getContainerContent();
}
render() {
const renderContainer = this.state.display ? styles.container : styles.hideDisplay;
return (
<div className={styles.container} id="container">
<h1>{this.props.book_title}</h1>
<h2>{this.props.book_author}</h2>
<img src = {this.props.img} alt="book cover"/>
<p>{this.props.summary}</p>
Purchase
</div> );
}
}
I think the problem stems from the getContainerContent method in your child component.
Why would a single child component be concerned with data that belongs to other child components?
A way you can solve this is to first declare in the parent component which props are you going to match the filter against when displaying child components.
Then, you could iterate over these declared props and decide whether the component should display a child component or not.
// parent comp
private shouldDisplayElement (element, searchTerm: string): boolean {
const propsToMatchFiltersAgainst = ['book_title', 'book_author', 'buy', /* etc... */];
let shouldDisplay = false;
for (const p of propsToMatchFiltersAgainst) {
if (`${element[p]}`.toLowerCase().includes(searchTerm.trim())) {
shouldDisplay = true;
}
}
return shouldDisplay;
}
// parent's render fn
<div className={styles.container}>
{this.state.importedBooks.map((element, index) => (
this.shouldDisplayElement(element, this.state.searchTerm)
? <Tile
key={index}
buy={element.amazon_product_url}
img={element.book_image}
summary={element.description}
url={element.book_image}
book_author={element.author} book_title={element.title}
/>
: null
))}
</div>
This way, given the current situation, you don't need to use the getContainerContent method in your child component anymore.

redux-form not populating FieldArray with InitialValues object

I'm working with react-redux-form 7.03 and attempting to populate fields from a database. In the interests of simplifying to determine where my issue is, I've created a static array of 1 object to try to get information to display.
I'm fairly new to React and Redux, and I've been fighting this for three days now. I've been using the examples from https://codesandbox.io/s/qDjw3zGG and the redux-form examples with no luck.
Basic issue is that in the props, I'm seeing initialValue:xmlConfigDataSet with the correct information in the object (array with 1 object correctly filled in). However that is not being passed to the fields property to RenderRows. Debugging fields shows a length of 0 and it just passes over the map() and never renders.
import React, {Component} from 'react'
import {connect} from 'react-redux'
import { Field, FieldArray, reduxForm } from 'redux-form'
class XMLMatchUpForm extends Component {
constructor(props){
super(props);
this.state = {}
}
render(){
return (
<FieldArray name="xmlConfigDataSet" component={RenderRows} />
)
};
const RenderRows = ({fields, meta}) => (
<div>
{fields.map((field, index) => {
const value = fields.get(index);
return <RenderStaticField name={field} value = {value} />
})}
</div>
)
const RenderStaticField = (props) => {
<Field name={`${props.name}.MW_MD_VALUE`} component="input" />
}
XMLMatchUpForm = reduxForm({
form: "XMLMatchUpForm"
}) (XMLMatchUpForm);
function mapStateToProps(state) {
return {
initialValues: {
xmlConfigDataSet:[{"MW_XS_ID":1314,"MW_MD_ID":null,"MW_XDM_VALUE":"Silver Spring","MW_XS_TAG_NAME":"receivercity"}]
}
};
}
export default connect(mapStateToProps, {fetchXMLConfig}) (XMLMatchUpForm);
(ignore the {fetchXMLConfig} in the example, that is actually the action it is caling to get the xmlConfigDataSet, as I said above, I'm trying to simplify this to determine where the issue is.
Any ideas, or pointers to clear examples are welcome.

Error: cannot find name ionViewDidLeave

I'm not sure where I'm going wrong with ionViewDidLeave. I'm getting an error from the terminal that says "cannot find name ionViewDidLeave". Is there something I have to import to use it? I have already imported the navController.
Here is my
ts.file
import { Component } from '#angular/core';
import { NavController, ModalController } from 'ionic-angular';
import { EditPost } from '../edit-post/edit-post';
import { LoadingController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class Home {
buttonColor: string = '#787083';
constructor (public navCtrl: NavController, public modalCtrl: ModalController, public loading: LoadingController) {
//OTHER FUNCTIONS
/*Navigate to edit page */
editPost(){
this.buttonColor = '#553481'; //change button background color on click
this.navCtrl.push(EditPost, {})
.catch(() => {
// Page requires authentication, re-direct to Login page
this.navCtrl.setRoot(Login, {routeToPage: 'EditPost'});
});
ionViewDidLeave(){
this.buttonColor = '#787083';
};
}// end of editPost()
}//close class
HTML
<ion-footer class="footer">
<ion-segment small class="footer">
<ion-segment-button id="post" value="post" (click)="postEvent()" [ngStyle]="{'background-color': buttonColor}" small> <span class="footer">NEW POST</span></ion-segment-button>
<ion-segment-button id="edit" value="edit" (click)="editPost()" [ngStyle]="{'background-color': buttonColor}" small> <span class="footer">Edit Post</span></ion-segment-button >
</ion-segment>
</ion-footer>
When you write inside an method
ionViewDidLeave()
you are calling a function from the current scope (editPost) function. The right way to call from the object would be:
this.ionViewDidLeave()
but I guess it's not right to call it (ionViewDidLeave is part of Ionic's page lifecycle), and I guess too that what you want to do is define this method and you have a type in your code. The right code should be:
export class Home {
buttonColor: string = '#787083';
constructor (public navCtrl: NavController, public modalCtrl: ModalController, public loading: LoadingController) {
editPost(){
this.buttonColor = '#553481'; //change button background color on click
this.navCtrl.push(EditPost, {})
.catch(() => {
// Page requires authentication, re-direct to Login page
this.navCtrl.setRoot(Login, {routeToPage: 'EditPost'});
});
}// end of editPost()
ionViewDidLeave(){
this.buttonColor = '#787083';
};
}//close class

Redux-Form: Not able to change value of input elements

I've been trying to implement a form in MapsAddrForm.jsx using Redux-Form and I can't seem to change the value of my input element. When the page loads, the input element does not respond to keyboard input, and when the form field submits, it returns an empty object to the parent component DistrictFinder. Beyond these two files, I've also added form:formReducer as an argument to combineReducers much like the simple example in the Redux-Form tutorials. Is there any way to restore the ability for the DistrictFinder to receive data objects from the address form? For reference, I'm using React 15.1.0, React-redux 4.4.5, ES6, and Redux-Form 5.3.1, all compiled using Webpack.
MapsAddrForm.jsx
import React, {Component} from 'react';
import { connect } from 'react-redux';
import {reduxForm} from 'redux-form';
class MapsAddrForm extends Component {
constructor(props) {
super(props);
}
render() {
const {fields: {address,address2}, handleSubmit} = this.props;
return (
<form onSubmit={handleSubmit}>
<div>
<input type="text" placeholder="Your address" {...address}/>
</div>
<button type="submit">Submit</button>
</form>
);
}
}
export default reduxForm({
form: 'addressForm',
fields: ['address']
})(MapsAddrForm);
DistrictFinder.jsx
import React, { Component, PropTypes } from 'react'
import MapsAddrForm from './MapsAddrForm.jsx'
import { connect } from 'react-redux'
import { changeAddress } from '../actions/index.jsx'
class DistrictFinder extends Component {
constructor(props) {
super(props);
this.handleAddrSubmit = this.handleAddrSubmit.bind(this);
}
handleAddrSubmit(data) {
console.log("Address received: " + JSON.stringify(data));
}
render() {
const {address, district} = this.props
return (
<div class="GMaps">
<h1>Find your district!</h1>
<MapsAddrForm onSubmit={this.handleAddrSubmit} />
<p>My district number is: {district}</p>
</div>
);
}
}
DistrictFinder.propTypes = {
district: PropTypes.string.isRequired,
dispatch: PropTypes.func.isRequired
};
function mapStateToProps(state) {
const { district } = state.infoChange;
return {
district
};
};
export default connect(mapStateToProps)(DistrictFinder);
I ran into this as well on redux-form#6.2.0
After looking at the source for one of the examples, I noticed the call to combineReducers has an explicit key "form" to the object argument. When I added this explicit key, the fields became editable.
// Correct
const reducer = combineReducers({
form: reduxFormReducer // mounted under "form"
})
If you have an existing app, like I do, you likely have this style es6 syntax from the various redux starters.
// Incorrect: results in the witnessed bad behavior
const reducer = combineReducers({
reduxFormReducer
})
See the combineReducers call at https://github.com/erikras/redux-form/blob/master/examples/simple/src/index.js#L10
It'd be interesting to see if this could be a constant that could be passed in and leveraged by the lib. "form" feels like a easily corruptible "namespace".

Resources