Updating AngularJS models on ng-click, DOM not responding - javascript

I have an input box and a textarea that are held inside a modal window that is open upon a button-click. The same input box and textarea are in use by a second modal with a different purpose. Each modal is under a different controller. So when I click on the button for the first controller, I want certain changes to apply to the modal as opposed to when I click on the other controller's button.
However, since these controllers share these input and textarea fields, sometimes information from one and the other pass to each other due to the ng-models within them. Other times, if I open a modal window, type into the inputs, close it, and then reopen the same window, the content still remains in the input fields.
This is all because I can't figure out how to update the content of these input/textarea fields from within my controllers. I'm not sure what I'm doing wrong. My models are not updating the DOM--help?
ControllerA, for new posts:
$scope.anonOrName = "anonymous"; //value when user posts anonymously
$scope.systemUserName="name from system here"; //value when user posts not-anon
//New title defined by the user for the post.
$scope.title="";
//post content the user fills in
$scope.postContent = "";
/*
* Operates the New Post modal window, calling functions from the modalManager
*factory
*/
$scope.newIdeaClick = function() {
$scope.title=""; //make sure title input is blank, doesn't work
$scope.postContent=""; //make sure the textbox is blank, doesn't work
document.getElementById('title').disabled = false; //allows user to type a new title, sometimes doesn't work
document.getElementById('anonymous').disabled = true; //user must post anonymously
modalManager.open('newPost'); //open the modal window
};
ControllerB, for new comments:
$scope.anonOrName = "anonymous";
$scope.systemUserName="name from system here";
//Title of the post the user is commenting on. The user cannot change this.
$scope.title="";
// Content of the textarea, the new comment written by the user.
$scope.postContent = "";
/*
* Operates the New comment modal window, calling functions from the modalManager factory
*/
$scope.newCommentClick = function() {
$scope.title="(some title will go here"; //sets the title, cannot be changed, doesn't work
$scope.postContent=""; //make sure the textbox is blank, doesn't work
document.getElementById('anonymous').disabled = false; //user can select anon or not
document.getElementById('title').disabled = true; //user may not choose new title
modalManager.open('newComment');
};
index.html has two calls of the following code, one under ControllerA, the other under ControllerB:
<modal>
<input ng-model="title" class="titleInputBox" id="title" />
<div class="commentPostName">
<div class="nameBlank">
{{anonOrName}}
</div>
<label>
Anonymous:
<input type="checkbox" ng-model="anonOrName" class="anonCheckBox" ng-true-value="anonymous" ng-false-value="{{systemUserName}}" id="anonymous" />
</label>
</div>
<textarea id="postBodyTextArea" ng-model="postContent">
</textarea>
</modal>
title and postContent are my two models I'm trying to set blank upon each time the respective post or comment button is clicked, calling the click functions defined in each controller. But they won't update the blanks in DOM.
Any help would be greatly appreciated!
Update: Through debug statements I've been able to determine that the values themselves have been reset to blank like I've written code for, but the change simply doesn't respect on the DOM. I've also tried to use $scope.$watch on these models to do the same thing, but no luck.
Update:
The selected answer worked, but I had various other bugs in my code that kept the correct answer from acting as if it had any effect. But it's working now! Just not with the above code.

The issue might be caused by scope inheritance. Instead of doing $scope.title, $scope.postContent you should store the string values inside an object as a property.
$scope.models = {
title : "",
postContent: ""
};
in markup
<input ng-model="models.title" class="titleInputBox" id="title" />
<textarea id="postBodyTextArea" ng-model="models.postContent">
The direct controller of the modal is likely not the controller you've written, instead a child of your controller. For details on this, please read Understanding Scopes, you will probably benefit from it as it is a common task.

Related

How to reset sap ui5 input fields by using javascript?

i have created one submission form by using java script i need to reset the input data by using on reset button.
Help me out of this.
reset: function() {
var oInput1 = sap.ui.getCore().byId("firstname");
oInput1.setValue("");*/
this.getViewById("firstname").setValue("");*/
}
input1.getId("firstname").setValue("");
onExit: function() {
input1.setValue("");
}
the code is not resetting the form data
First of all your provided code-sample is incorrect, please correct it.
Second, onExit is executed when your view is destroyed, setting the input value to empty is rather useless there.
If you want to reset data of your input-field when clicking a button you'll need to have the following elements:
1) an Input- & Button-control (with press-event) in your XML-view.
2) an id assigned to your Input-control to be able to refer to the control when pressing the reset-button.
3) The press-event from the button worked out in your controller.
XML
<Input id="firstname" value=""/>
<Button text="Reset" press="reset"/>
Controller
reset: function() {
var oInput1 = this.getView().byId("firstname");
oInput1.setValue("");
}

View only partially refreshed after $scope.$on()

In this AngularJS controller for a pre-filled form, fetching the data is triggered by an event using $broadcast and $on. However, when the data updates, only some of the corresponding fields get updated in the view.
$scope.currentHouse = {};
$scope.$on('houseInfoLoad', function(event, data) {
$scope.currentHouse = data.houseDetail; //does not refresh the view
console.log($scope.currentHouse); //output is correct
//the next three calls refresh the corresponding fields in the view
$scope.changeGarageRadioValue($scope.currentHouse.hasGarage);
utils.setSelection($scope.houseKeywords, $scope.currentHouse.keyword.id);
utils.setSelection($scope.houseTypes, $scope.currentHouse.type.id);
});
changeGarageRadioValue() essentially does what it says, and utils.setSelection(list, id) adds a selected = true property to the element of the list that has the id. This has the effect of setting the value of a select field (using isteven's multi-select plugin).
The view has a few text fields bound to properties of $scope.currentHouse, as well as these radio buttons and select fields.
The result is that the text fields sometimes do not get updated, however the select and radio buttons do.
Here's what I tried unsuccessfully:
Wrapping everything in a $timeout();
Calling $scope.$apply() after setting $scope.currentHouse (throws an error saying that we are already inside an $apply())
Changing the initial definition of $scope.currentHouse from {} to an object with each of the fields set to null.
Can anyone see what I am missing, or how to force trigger the refresh?
EDIT : with extracts from the view :
A text field:
<label>ADDITIONAL DESCRIPTION</label>
<div>
<input type="text" ng-model="currentHouse.additionalDescription" class="input-mandatory" value=""/>
</div>
A multi-select:
<label>TYPE</label>
<div>
<div directive-id="houseType" multi-select input-model="houseTypes" output-model="currentHouse.type" button-label="text" item-label="text" selection-mode="single" default-label="Select" tick-property="selected" ></div>
</div>
The radio buttons :
<div><label>HAS GARAGE</label></div>
<div>
<div id="radiobuttonNo" ng-click="changeGarageRadioValue(false);">
NO
</div>
<div id="radiobuttonYes" ng-click="changeGarageRadioValue(true);" class="active">
YES
</div>
</div>
EDIT #2 as per Alok Singh's suggestion:
I tried putting data.houseDetail into $scope.currentHouse.house instead of $scope.currentHouse directly, and changing the view accordingly. Still no results.
$scope.currentHouse = data.houseDetail
You cannot get the updated value of currentHouse because its a model.
So change the above code i.e
$scope.currentHouse.house = data.houseDetail

AngularJS - How to keep original value if I don't hit submit

I have a list of users on the left with the details on the right.
The right details are handled with a form, and inputs with ng-model. So when I click on a user on the left, I change the selected user and the model automatically shows me the proper details on the right.
I also have a submit button that saves changes to the server.
This all works well, but the problem is that if I change a user's name for example, click on another user, and then come back to the first user, I see the changed name, but the info was never saved on the server. So the client might think that the info was changed on the server, when it wasn't. After I hit refresh, I get the old, server values back.
So how can I revert model changes if I switch the model before hitting save?
By the way, I'm using ng-model instead of using {{ }} in the value field, because AngularJS validators don't work unless you use ng-model
Thanks
Everytime user selects the item in the left, copy that selected object into new variable. You can copy using angular.copy function. Then show that new variable on the right side in the form. Right now changes are "saved" because you are referencing items in your array (so when you change something in form it is changed into this item in array). If you have new variable for selectedItem you won't have this problem any more.
I suggest binding an object to the input fields of your form and using ng-submit to call a function to update your values on the server, much like Nemanja suggested.
I went ahead and made a simple JS Fiddle so you have a small example to structure your code around. Hope it helps!
HTML:
<form ng-model="data" ng-submit="simple.saveName()">
Name: {{ simple.data.name }}
<br />Twitter: {{ simple.data.twitter }}
<br />
<br />New name:
<input type="text" ng-model="simple.newName" />
<br />
<button>Submit</button>
</form>
JavaScript:
(function () {
angular
.module('app', [])
.controller('simpleController', SimpleController);
function SimpleController() {
var vm = this;
// Public stuff.
vm.data = {
name: 'Joe',
twitter: '#martellaj'
};
vm.newName;
vm.saveName = saveName;
// Private stuff.
function saveName() {
console.log('Saving name...');
vm.data.name = vm.newName;
};
};
})();

Making Meteor reactive for html elements

So I have a modal box that allows the user to edit / save some data.
I just want to add that unlike other Meteor apps, I don't want to save the data straight away - I want the user to fill in all the fields before hitting save where it will save to the database and send to server etc. This is mainly because I want the user to be able to hit the "cancel" button to revert all changes.
I have a drop down box at the start of the form where depending on the value, fields will be shown or hidden
<select class="form-control" id="ddlNewInputType" placeholder="Enter your input type">
<option value="input">Input</option>
<option value="formula">Formula</option>
</select>
And I have a handlebar around a field like this to determine whether I want to show it
{{#if isFormula }}
<div class="row">
<input type="text"
id="txtNewInputFormula" placeholder="Enter formula">
</div>
{{/if}}
With a helper looking like this
isFormula: ->
$('#ddlNewInputType').val() == 'formula'
However, this doesn't work. Aside from when it first loads onto the page, it never hits isFormula, probably because Meteor doesn't consider any of the HTML elements as reactive so it never re-evaluates when the HTML element changes.
What is a suitable way to get around this? Is it possible to make something reactive explicitly in Meteor? I was also considering putting the dropdown list value into a session variable but that just seems messy because I'm going to need to manage this session variable (remember to clear it when the modal box closes etc.)
Your analysis is correct - a reactive variable needs to be involved in order for your helper to reevaluate after changing the select element. The basic strategy looks like:
Initialize a reactive variable when the template is created.
Whenever the select changes, update the reactive variable.
Read the reactive variable in your helper.
Rather than use a session variable, let's use a ReactiveVar scoped to your template. Here's an example set of modifications:
Template.myTemplate.helpers({
isFormula: function() {
return Template.instance().isFormula.get();
}
});
Template.myTemplate.events({
'change #ddlNewInputType': function (e, template) {
var isFormula = $(e.currentTarget).val() === 'formula';
template.isFormula.set(isFormula);
}
});
Template.myTemplate.created = function() {
// in your code, default this to the current value from
// your database rather than false
this.isFormula = new ReactiveVar(false);
};
Remember that you'll need to also do:
$ meteor add reactive-var
See my post on scoped reactivity for a full explanation of this technique.

KnockoutJS: Posting only visible form elements

I have just started using Knockout.js My form has elements which I call questions. I hide/show them based on user selections. When user hits the submit button I want to post only the visible questions at the time of submit. What I have is this:
// length of Results(questionArray) is 260
var vmToPost = viewModel;
delete vmToPost.__ko_mapping__;
ko.utils.arrayForEach(vmToPost.Results(), function (question) {
if (!(vmToPost.getQuestion(question.QuestionID()).visible())) {
ko.utils.arrayRemoveItem(vmToPost.Results(), question);
}
});
The util function arrayForEach is behaving strange. It loops through the array very differntly. I had to hit the submit button 7 times to get all the visible elements and come out of the util function. It doesnt throw any error message in the console or the fiddler.
What am I doing wrong. Please help.
Html contains a built-in way to skip items from being submitted. It's the disabled attribute, which can be controlled using Knockout with the enable or disable bindings.
<div data-bind="visible: visible">
<label>Name: <input name="name" data-bind="enable: visible"></label>
</div>

Categories