0

I'm pretty new to AngularJS, and in my inquisitive nature have attempted (and succeeded in most respects) in writing a news page, that allows users to comment on each article.

What I'm totally unhappy with though is my use of classic Javascript to get the story from the forms dynamically; you can see that I'm creating input fields that I am using a GetElementById on. Is there anyway to tidy this up with the two way data binding? I originally did this, but my lack of knowledge meant that the model was bound to BOTH forms; what would the the 'Angular' way around this? Primarily I can see that the addComment function is just Javascript - I know I can do this more succinctly in JQuery, but don't want to. I've got it working with a single 'comment' just fine, but can't see how I would approach multiple.

The second part is my form validation doesn't work. My guess is that my stab into it isn't great.

        var app = angular.module("ngStoryTime", []);

        var _stories = [
        {
            Id: 1,
            Title: 'Man Falls Off The World!',
            Body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
            Date: '7 March 2015',
            Images: [],
            Comments: [{ Body:'LOL!', Name:'Michael', Date:'1 April 2015' }, { Body:'Tis a shame that.', Name:'William', Date:'1 April 2015' }]
        },
        {
            Id: 2,
            Title: 'Woman Eats Badger!',
            Body: 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum',
            Date: '8 March 2015',
            Images: [],
            Comments: []
        }
        ];

        app.controller('StoryController', function($scope){

            $scope.pageTitle = 'Welcome to the StoryTime website!';

            //  Initialise the story, and blank Comment property here
            this.Stories = _stories;

            this.addComment = function(story){
                //  Is there a better way to do this??
                var commentValue = document.getElementById('txtComment_' + story.Id);  
                var nameValue = document.getElementById('txtName_' + story.Id);  

                //  Create the object that holds the new comment value  
                var myNewComment = { 
                    Body: commentValue.value, 
                    Name: nameValue.value,
                    Date: '1 May 2015'
                };

                //  Add the comment to the array
                story.Comments.push(myNewComment);
                commentValue.value = '';    
                nameValue.value = '';            
            };
        });

<body ng-controller='StoryController as storyCtrl'>

<h1>{{pageTitle}}</h1>

<!-- Alias the controller for use in this section -->
<div ng-repeat="story in storyCtrl.Stories">

    <!-- For each Story, detail and show it -->        
    <h2>{{story.Title}} </h2>
    <h3>{{story.Date | date:'medium' }}</h3>
    <p>{{story.Body}}

    <div ng-repeat="comment in story.Comments">
        <h4>{{comment.Name}} - {{comment.Date | date:'medium'}} </h4>
        <em>"{{comment.Body}}"</em>
    </div>    

    <!-- Show and hide an introduction depending on if a story has a comment, or not -->
    <h4 ng-show="story.Comments.length > 0">Have a Comment? There are {{story.Comments.length}} comments made so far!</h4>
    <h4 ng-show="story.Comments.length == 0">Have a Comment? Be the first to comment on this excellent piece of journalism</h4>

    <!-- Start of the new form that holds the story's comments, we put the story's Id on all the HtmL so we can get this later, but i'm not sure if this is actually a good idea, yet. -->
    <form name="frmStory_{{story.Id}}" ng-submit="storyCtrl.addComment(story)">   
        Name: <br />
        <input id="txtName_{{story.Id}}" required /><br />    
        Comment:<br/>
        <textarea id="txtComment_{{story.Id}}" required></textarea>
        <button ng-disabled="frmStory_{{story.Id}}.$invalid">Add My Comment</button>
    </form> 
    <hr/>
</div>
</body>
1
  • You can use the ng-model attribute on those form controls, this will bind the input to a variable on $scope. Commented Apr 2, 2015 at 18:48

2 Answers 2

1

ng-model is a key here. Every time ng-repeat iterate through given collection it will create different scope for each piece of the repeated html code respectively to given object. Using ng-model allows you to manage the data in given scope.

<form name="frmStory_{{story.Id}}" ng-submit="storyCtrl.addComment(story)">   
    Name: <br />
    <input ng-model="story.newComment.Name" required /><br />    
    Comment:<br/>
    <textarea ng-model="story.newComment.Body" required></textarea>
    <button ng-disabled="frmStory_{{story.Id}}.$invalid">Add My Comment</button>
</form>

Secondly in your code :

this.addComment = function(story)

you are referencing to the instance of the controller, better way to do this is bind everything that has connection with view with $scope

$scope.addComment = function(story)

More about ng-model: https://docs.angularjs.org/api/ng/directive/ngModel

Understaning angular model and scope system is a huge milestone to understand the Angular way to build apps. I encourage you to start with that.

Sign up to request clarification or add additional context in comments.

2 Comments

OK this helped a great deal, so you comment on each iteration creating a different scope nailed it. I though it did, but couldn't quite picture it in my head 'how' it would work.It's working perfectly now as intended with no Javascript. Thanks!
Scope feature is often regarded as the most confusing part of the framework functionality. Try chrome extension 'ng-inspector for AngularJS'. It helped me to figure out how scopes are set and dependencies between them.
0

Write functions in your controller this way:

$scope.yourFunctionName = function () {

}

More info here: https://docs.angularjs.org/guide/controller

As far as the form validation failing, can you paste some error messages you are getting?

1 Comment

I was being a noob it appears, the error was down to not using the controller reference :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.