Edit/remove methods

Hi, I m trying to create a " post page" and im really stuck for some time, I’m trying to make a page where you can add/edit/remove a post, but I can’t make the post remove/edit to work. What am I doing wrong?

 'create_a_standard_post': function () {
    return Posts.insert({type: 'standard'})
},

'create_a_post': function (type) {
    return Posts.insert({type: type});
},

'post.find': function (id) {
    return Posts.findOne({_id: id});
},

'post.remove': function (post) {
    if (!this.userId) {
        throw new Meteor.Error('not-authorized');
    }
    Posts.remove(post._id);
},
'posts.list': function () {
    return Posts.find().fetch();
},

'post.add': function (data) {
    if (!this.userId) {
        throw new Meteor.Error('not-authorized');
    }
    data.userId = this.userId;
    console.log(data);
    Posts.insert ({
        text: data.name ,
        createdAt: new Date(),
        userId: this.userId
    });
}
,
'post.edit': function(id, data) {
    if(!this.userId){
        throw new Meteor.Error('not-authorized');
    }
    Posts.update(id, {$set: {name: data.name}});
}
});
class PostsList extends React.Component {
    constructor() {
        super();
    }
    removePost() {
        Meteor.call('post.remove', this.props.post)
    }

    render() {
        const {loading, posts} = this.props;
        if (loading) {
            return (
                <div>Loading...</div>
            )
        } else {
            return (
                <div>
                    {
                        posts.map((post) => {
                            return (
                                <div key={post._id}>
                                    <div>{post.name}</div>
                                    <a href={"/post/edit/" + post._id}>Edit</a>
                                    <button onClick={this.removePost.bind(this)}>Remove</button>
                                </div>
                            )
                        })
                    }
                    <a href="/posts/create">Create a post</a>
                </div>
            )
        }
    }
}

export default createContainer(() => {
    const handle = Meteor.subscribe('posts');

    return {
        loading: !handle.ready(),
        posts: Posts.find().fetch(),
    }
}, PostsList);
export default class PostsCreate extends Component {
    constructor() {
        super();
    }

    addPost(post) {
        Meteor.call('post.add', post, (err, result) => {
            if(!err) {
                alert('post added!');
            }
        });
    }

    render() {
        return (
            <div>
                <Formsy.Form onValidSubmit={this.addPost.bind(this)}>
                    <Input type="text" name="name" placeholder="" value=""/>
                    <button type="submit" className="btn btn-default">Add post</button>
                </Formsy.Form>
                <a href="/posts">posts</a>
            </div>
        );
    }
}
export default class PostEdit extends Component {
    constructor() {
        super();
        this.state = {loading: true, post: null}
    }

    componentDidMount() {
        Meteor.call('post.find', route.current().params.id, (err, res) => {
            this.setState({
                loading: false,
                post: res
            })
        })
    }

    editPost (data) {
        Meteor.call('post.edit', this.state.post._id, data, (err, result) => {
            if(!err) {
                alert('post modified!');
            }
        });
    }

    render() {
        if (this.state.loading) {
            return (
                <div>Loading...</div>
            )
        } else {
            return (
                <div>
                    <Formsy.Form onValidSubmit={this.editPost().bind(this)}>
                        <Input type="text" name="name" placeholder="post" value={this.state.post.name}/>
                        <button type="submit" className="btn btn-default">Edit</button>
                    </Formsy.Form>
                    <a href="/posts">Back to list</a>
                </div>
            );
        }
    }
}

I get this error :

Exception while invoking method ‘post.remove’ TypeError: Cannot read property ‘_id’ of null

First of all for the post.remove method

Here in your component


  removePost() {
        Meteor.call('post.remove', this.props.post)
    }

You do not have any post in this.props

Instead pass an argument to the method


 removePost(post) {
        Meteor.call('post.remove', post)
    }

And call it like this

<button onClick={() => this.removePost(post)}>Remove</button>

In your PostsCreate
<Formsy.Form onValidSubmit={this.addPost.bind(this)}>
You should pass post
<Formsy.Form onValidSubmit={() => this.addPost(post)}>
P.S I do not see post declared anywhere in the component be sure to check that please.
Same problem is in PostEdit component method editPost

Sorry for not explaining in the details, I’ll come back and add some details if you need, but hope this helps.

Thanks for you response, but if i want only the owner to delete/edit the “post” i dont have to use this.props?

also i edited the ‘post.add’, it now should show the id and the userId, but how can i make the delete/edite see if its the owner and get the id?

'post.add': function (data, userId) {
        if (!this.userId) {
            throw new Meteor.Error('not-authorized');
        }
        console.log(data);
        Posts.insert (data, data.userId = this.userId);
    }

How can i declare it?

made the changes you said and i got

Uncaught ReferenceError: post is not defined

Are you new to JS in general?

Posts.insert (data, data.userId = this.userId);

This is a function call. Function calls accept only arguments you cannot do assignments there. Do this instead

data.userId = this.userId
Posts.insert (data)

Then in your delete method you findOne the post that should be deleted and check if it’s userId matched this.userId

It is probably because you do not have any post defined in your PostsCreate component.

I’ve just started so I’m newbie with everything, I still don’t get alot of stuff :disappointed:

This makes sense now.[quote=“hayk, post:6, topic:36423”]
Then in your delete method you findOne the post that should be deleted and check if it’s userId matched this.userId
[/quote]

So a post have :

{
  "_id": "sCw3gNmgBkY9dTrf7",
  "name": "bla bla bla",
  "userId": "B4bH7suxTXStrB5bz"
}

If i want only the owner to delete the post i need to findOne the userId, right?So the method should look like this ?

'post.remove'(post){
        Posts.findOne(userId);
        if (userId !== this.userId) {
            throw new Meteor.Error('not-authorized');
        }
            Posts.remove(post);
    },

I highly recommend you read the Meteor Guide. It covers all the questions you’re asking.

However, before doing that you should get a grounding in at least the fundamentals of JavaScript or you will just become increasingly confused and frustrated.

I just ask so that I am able to give you more proper help. I have only a one year experience and It would take us forever if we go over basics in the forums and that wouldn’t help you much. Instead let me give you a proper resource to learn the basics.
https://medium.freecodecamp.com/my-giant-javascript-basics-course-is-now-live-on-youtube-and-its-100-free-9020a21bbc27

I think this may be a good start. Once you’ve got a good grasp on these learning Meteor or any other framework will be much easier.
You can use Meteor guide as mentioned by Rob and meteor tutorials here
https://www.meteor.com/tutorials/react/creating-an-app

You would need to save the userId in a variable like this

const userId = Posts.findOne(userId).userId

Or you can just put the current userId in your query object

post.userId = this.userId