I have a simple form with a checkbox which clicked deletes a property from an object.
Here is the controller:
app.controller('PropController', function ($scope) {
var str = '{"meta":{"aprop":"lprop"},"props":{"gprop":12,"lprop":9,"wrop":5}}';
$scope.filecontent = JSON.parse(str);
$scope.delprop = false;
$scope.propobj = $scope.filecontent.props;
$scope.proptodel = $scope.filecontent.meta.prop;
var mainvalue = $scope.propobj[$scope.proptodel];
$scope.$watch('delprop', function () {
if ($scope.delprop == true) {
delete $scope.propobj[$scope.proptodel];
} else {
$scope.propobj[$scope.proptodel] = mainvalue;
}
});
And the view:
<div ng-app="SomeProperties" ng-controller="PropController">
<div ng-if="proptodel">
there is a property to delete: {{proptodel}}
<form><input type="checkbox" ng-model="delprop"></form>
filecontent: {{filecontent}}
</div>
<div ng-if="!proptodel">
there is NO property to delete
</div>
</div>
The app on jsfiddle.
The problem appears when the form is in the ng-if, it stops behaving. As you can try it in the jsfiddle, when I delete ng-if="proptodel" from the div containing the form, it working normally. What is the explanation of this?
You need to put the delprop into in object to make ng-model work properly. That means your markup should have:
<form><input type="checkbox" ng-model="obj.delprop"></form>
And your Javascript code should look like:
$scope.obj = {
delprop: false
};
$scope.propobj = $scope.filecontent.props;
$scope.proptodel = $scope.filecontent.meta.prop;
var mainvalue = $scope.propobj[$scope.proptodel];
$scope.$watch('obj.delprop', function () {
if ($scope.obj.delprop == true) {
delete $scope.propobj[$scope.proptodel];
} else {
$scope.propobj[$scope.proptodel] = mainvalue;
}
});
Of course you should find a proper name for the object as obj is really bad and generic ;-)
Related
I try to learn SAPUI5 with Samples frpm Demo kit Input - Checked. I get an error message: oInput.getBinding is not a function
I have a simple input field xml:
<Label text="Name" required="false" width="60%" visible="true"/>
<Input id="nameInput" type="Text" enabled="true" visible="true" valueHelpOnly="false" required="true" width="60%" valueStateText="Name must not be empty." maxLength="0" value="{previewModel>/name}" change= "onChange"/>
and my controller:
_validateInput: function(oInput) {
var oView = this.getView().byId("nameInput");
oView.setModel(this.getView().getModel("previewModel"));
var oBinding = oInput.getBinding("value");
var sValueState = "None";
var bValidationError = false;
try {
oBinding.getType().validateValue(oInput.getValue());
} catch (oException) {
sValueState = "Error";
bValidationError = true;
}
oInput.setValueState(sValueState);
return bValidationError;
},
/**
* Event handler for the continue button
*/
onContinue : function () {
// collect input controls
var that = this;
var oView = this.getView();
var aInputs =oView.byId("nameInput");
var bValidationError = false;
// check that inputs are not empty
// this does not happen during data binding as this is only triggered by changes
jQuery.each(aInputs, function (i, oInput) {
bValidationError = that._validateInput(oInput) || bValidationError;
});
// output result
if (!bValidationError) {
MessageToast.show("The input is validated. You could now continue to the next screen");
} else {
MessageBox.alert("A validation error has occured. Complete your input first");
}
},
// onChange update valueState of input
onChange: function(oEvent) {
var oInput = oEvent.getSource();
this._validateInput(oInput);
},
Can someone explain to me how I can set the Model?
Your model is fine and correctly binded.
The problem in your code is here, in the onContinue function
jQuery.each(aInputs, function (i, oInput) {
bValidationError = that._validateInput(oInput) || bValidationError;
});
aInput is not an array, so your code is not iterating on an array element.
To quickly fix this, you can put parentheses around the declaration like this:
var aInputs = [
oView.byId("nameInput")
];
Also, you could remove the first two lines of the _validateInput method since they are useless...
Usually, we set the model once the view is loaded, not when the value is changed. For example, if you would like to set a JSONModel with the name "previewModel", you can do as mentioned below.
Note that onInit is called when the controller is initialized. If you bind the model properly as follows, then the oEvent.getSource().getBinding("value") will return the expected value.
onInit: function(){
var oView = this.getView().byId("nameInput");
oView.setModel(new sap.ui.model.json.JSONModel({
name : "HELLO"
}), "previewModel");
},
onChange: function(oEvent) {
var oInput = oEvent.getSource();
this._validateInput(oInput);
},
...
Also, for validating the input text, you can do the following:
_validateInput: function(oInput) {
var oBinding = oInput.getBinding("value");
var sValueState = "None";
var sValueStateText = "";
var bValidationError = false;
if(oBinding.getValue().length === 0){
sValueState = "Error";
sValueStateText = "Custom Error"
}
oInput.setValueState(sValueState);
if(sValueState === "Error"){
oInput.setValueStateText(sValueStateText);
}
return bValidationError;
},
Please note that the code above is not high quality and production ready as it's a quick response to this post :)
Good day. I have read and done almost all of the solution in the questions but cant seem to solve my problem. As written in my question, in mvc, i am passing a value from controller to view a string and then get by javascript to run a modal if ever a certain condition is met. please help. thanks.
here is the code in my controller:
public ActionResult Series()
{
List<sample> series = db.samples.Where(x => x.status == "False").ToList();
if ( series.Count == 0)
{
ViewBag.Info = "None";
}
else {
ViewBag.Series = series;
ViewBag.Info = "Have";
}
return View();
}
My View:
<input type="text" value="#ViewBag.Info" id="info" name="info" />
My Javascript:
#section Scripts{
<script>
$(window).on('load', function () {
var modelll = document.getElementById("#(ViewBag.Info)").value;
var s_end = document.getElementById("myNumber2").value;
var s_current = document.getElementById("myNumber3").value;
var s_status1 = document.getElementById("status").value;
var s_id1 = parseInt(document.getElementById("myNumber").value);
var s_end2 = parseInt(s_end, 10);
var s_current2 = parseInt(s_current, 10);
var x = parseInt(s_current, 10) + 1;
document.getElementById("item1").value = s_id1;
document.getElementById("item2").value = s_end;
document.getElementById("item3").value = x;
document.getElementById("status2").value = s_status1;
if (modelll === 'Have')
{
if ((s_current2 > s_end2) && (s_current2 != s_end2)) {
$('#myModal').modal({ backdrop: 'static', keyboard: false });
$('#myModal').modal('show');
}
}
else
{
$('#myModal').modal({ backdrop: 'static', keyboard:false });
$('#myModal').modal('show');
}
});
</script>
}
getElementById need an ID but you are passing #ViewBag.Info. change it to :
var modelll = document.getElementById("info").value;
also you are making many extra variables which are not really needed. for example to get what you have in s_current2, you can use
var s_current = parseInt(document.getElementById("myNumber3").value, 10);
no need to create another variable to convert it to integer.
To get the value from textbox
var modelll = document.getElementById("info");
To set the value to textbox
document.getElementById("info").value = var modelll;
you are using #ViewBag.Info instead of element id.
Following line is causing the problem in your code :
var modelll = document.getElementById("#(ViewBag.Info)").value;
// document.getElementById needs Id but you are passing #(ViewBag.Info) which is wrong
var modelll = document.getElementById("info").value; //info id of your textbox
// now check
if (modelll === 'Have')
{ }
else
{ }
I have a problem with my Script. I want to do the following steps in this order:
1. Save the text in the input field.
2. Delete all text in the input field.
3. Reload the same text that was deleted before in the input field.
The problem with my script is that the ug()- function writes undefined in my textbox instead of the string that should be stored in var exput. The alert(exput) however shows me the correct content.
Help would be very much appreciated. And I'm sure there is better ways to do that, I'm quite new to this stuff.
HTML
<textarea id="a" style="width: 320px; height: 200px;"></textarea>
<input type="checkbox" id="remember" onclick="merker();deleter();ug()" />
Javascript
function merker() {
var merkzeug = document.getElementById('a').value;
ug(merkzeug);
};
function deleter() {
if(document.getElementById('remember').checked == true)
{
document.getElementById('a').value = "";
}
else {document.getElementById('a').value = "";
}
};
function ug(exput) {
alert(exput);
document.getElementById('a').value = exput;
};
Your code is calling merker(); deleter(); ug(); in the onclick event, but ug() is already called by merker(). You should be doing this instead:
function merker() {
var merkzeug = document.getElementById('a').value;
deleter();
ug(merkzeug);
};
function deleter() {
if(document.getElementById('remember').checked == true)
{
document.getElementById('a').value = "";
}
else {document.getElementById('a').value = "";
}
};
function ug(exput) {
alert(exput);
document.getElementById('a').value = exput;
};
<textarea id="a" style="width: 320px; height: 200px;"></textarea>
<input type="checkbox" id="remember" onclick="merker();" />
I changed Your Javascript:
function merker() {
merkzeug = document.getElementById('a').value;//global variable without var
ug();//why You use it here? I think only for test. So delete it after.
};
function deleter() {
if(document.getElementById('remember').checked == true)
{
document.getElementById('a').value = "";
}
else {document.getElementById('a').value = "";
}
};
function ug() {
alert(merkzeug);
document.getElementById('a').value =merkzeug;
};
Problems with your code:
method ug was used with argument and without argument ( i changed to without )
to restore deleted value it must be saved to some variable, i saved to global merkzeug variable - this is not good practice but sufficient in this case
next i used merkzeug to restore value in textarea in ug() function
i do not know why You using ug() two times? maybe delete one of them is good thing to do.
In plunker - https://plnkr.co/edit/fc6iJBL80KcNSpaBd0s9?p=info
problem is: you pass undefined variable in the last ug function:
you do: merker(value) -> ug(value); delete(); ug(/*nothing*/);
or you set your merkzeung variable global or it will never be re-inserted in your imput:
var merkzeug = null;
function merker() {
merkzeug = document.getElementById('a').value;
ug(merkzeug);
};
function deleter() {
if(document.getElementById('remember').checked == true)
{
document.getElementById('a').value = "";
}
else {document.getElementById('a').value = "";
}
};
function ug(exput) {
if (typeof exput === 'undefined') exput = merkzeung;
alert(exput);
document.getElementById('a').value = exput;
};
I'm at my wits end! In angular I've got a controller and a view.
There are 2 dropdowns on the page which need to reset to default once the restart button has been clicked.
I can set the value of the boxes as they render by pushing a "select" option into the collection inside the controller. However, when the reset button is pressed, which runs the init() method again, the dropdowns should be set back to the first value. This doesn't occur, the values for $scope.selectedYear and $scope.selectedReport remain as they did before the reset button was pressed.
This is the full code for the controller
function TreeReportsCHLController($scope, $q, $routeParams, reportsDashboardResource, navigationService, notificationsService, dialogService, entriesManageDashboardResource, $timeout) {
// Methods
var generalError = function () {
notificationsService.error("Ooops", "There was an error fetching the data");
$scope.actionInProgress = false;
}
// Scope
$scope.selectedYear = "";
$scope.init = function () {
$scope.hasCompleted = false;
$scope.actionInProgress = false;
$scope.yearSelected = false;
$scope.reportTypes = ["Choose", "Entered", "ShortListed", "Winner", "Recieved"];
$scope.selectedReport = "";
$scope.entryYears = new Array();
$scope.entryYears.push("Choose a Year");
entriesManageDashboardResource.getEntryYears().then(function (response) {
angular.forEach(response, function (value, key) {
$scope.entryYears.push(value);
});
});
$scope.selectedYear = $scope.entryYears[0];
$scope.selectedReport = $scope.reportTypes[0];
};
$scope.yearHasSelected = function(selectedYear) {
$scope.yearSelected = true;
$scope.selectedYear = selectedYear;
};
$scope.generateFile = function (selectedReport) {
$scope.actionInProgress = true;
var reportDetail = {
entryYear: $scope.selectedYear,
chosenEntryStatus: selectedReport
};
reportsDashboardResource.generateEntriesReportDownloadLink(reportDetail).then(function (response) {
if (response.Successful) {
$scope.hasCompleted = true;
} else {
notificationsService.error("Ooops", response.ErrorMessage);
}
$scope.actionInProgress = false;
}, generalError);
};
$scope.restart = function () {
$scope.init();
}
// Initialise Page
$scope.init();
}
angular.module("umbraco").controller("ReportsDashboardController", TreeReportsCHLController)
this is the code with the dropdowns in it;
<table>
<tr>
<td>Get a report for year: {{selectedYear}}</td>
<td><select ng-model="selectedYear" ng-change="yearHasSelected(selectedYear)" ng-options="year for year in entryYears" no-dirty-check></select></td>
</tr>
<tr ng-show="!hasCompleted && yearSelected">
<td>
Get Report Type:
</td>
<td>
<select ng-model="selectedReport" ng-change="generateFile(selectedReport)" ng-options="status for status in reportTypes" no-dirty-check ng-disabled="actionInProgress"></select>
</td>
</tr>
</table>
I've also done a further test where I simply set $scope.selectedYear to $scope.entryYears[0] within the reset method. When I console.log $scope.selectedYear here, the value confirms it has been changed, but strangely where I've outputted the $scope.selectedYear / {{selectedYear}} to the page for testing, this does not update. It's almost as though the binding between the controller and the view isn't occuring.
Any help?
Thank-you.
Here's a working plunk that is somewhat stripped down since I didn't have access to of the services that your are injecting into your controller. The changes I made in the controller are:
First,
$scope.entryYears = new Array();
becomes
$scope.entryYears = [];
as this is the preferred way to declare an array in js.
Second, I removed $scope.apply() that was wrapping
$scope.selectedYear = $scope.entryYears[0];
$scope.selectedReport = $scope.reportTypes[0];
as this was causing infinite digest cycles.
I've a list on ng-repeat that displays a list of results from a $http query (bind to an input). I'd like both for the list to disappear when the user clicks on one of the results and for the initial empty value of the model to be restored.
Basically, the functionality is as follows:
User searches term, list displays results, user clicks on result, list disappears, user clicks on input again to make another search, list with new results appear.
So far I've managed to make the list disappear, but not to make it appear again when the user makes another search.
Here's the relevant code:
<input type="text" ng-model="name" ng-click="Research()"/>
<ul ng-hide="clicked" ng-show="retype">
<li ng-repeat="result in results" ng-click="getDetails(result.id)">{{result.title}}</li>
</ul>
And the JS:
function Ctrl($scope, $http) {
var get_results = function(name) {
if (name) {
$http.get('http://api.discogs.com/database/search?type=artist&q='+ name +'&page=1&per_page=8').
success(function(data3) {
$scope.results = data3.results;
});
}
}
$scope.name = '';
$scope.$watch('name', get_results, true);
$scope.getDetails = function (id) {
$http.get('http://api.discogs.com/artists/' + id).
success(function(data) {
$scope.artist = data;
});
$http.get('http://api.discogs.com/artists/' + id + '/releases?page=1&per_page=500').
success(function(data2) {
$scope.releases = data2.releases;
});
$scope.clicked = true;
}
function Research(){
$scope.retype = true,
$scope.name = '';
}
Plunkr is down, I'll make one as soon as possible. Any idea about what am I missing?
I tidied up your code a little bit. Please note that the div is shown only when artist is defined. So when it is set to undefined by the $scope.clear() method, the mentioned div is hidden.
Html part:
<div ng-controller="Ctrl">
<input type="text" ng-model="name" ng-focus="clear()"/>
<ul>
<li ng-repeat="result in results" ng-click="getDetails(result.id)">{{result.title}}</li>
</ul>
<div ng-show="artist">
<h1>Artist</h1>
<ul>
<li>{{artist.name}}</li>
<li>{{artist.release_url}}</li>
<li>{{artist.uri}}</li>
<li>{{artist.resource_url}}</li>
</ul>
</div>
</div>
JavaScript part:
var myApp = angular.module('myApp',[]);
function Ctrl($scope, $http) {
$scope.name = undefined;
$scope.artist = undefined;
$scope.results = undefined;
var search = function (name) {
if (name) {
$http.get('http://api.discogs.com/database/search?type=artist&q='+ name +'&page=1&per_page=8').
success(function(data3) {
$scope.results = data3.results;
});
}
}
$scope.$watch('name', search, true);
$scope.getDetails = function (id) {
$http.get('http://api.discogs.com/artists/' + id).
success(function(data) {
$scope.artist = data;
});
$http.get('http://api.discogs.com/artists/' + id + '/releases?page=1&per_page=500').
success(function(data2) {
$scope.releases = data2.releases;
});
}
$scope.clear = function () {
$scope.name = undefined;
$scope.artist = undefined;
$scope.results = undefined;
}
}
There is working JSFiddle.
Your Research function is unnecessary because you don't need ng-show and ng-hide same time...
secondly you set clicked to ok but never set it false again after your research done...
here is working PLUNKER
Try using just one ng-hide or ng-show, instead of both. Since you never set clicked back to false, it is probably overriding the retype.
Both functions are two-way, so you can just use ng-hide="clicked", and inside function Research, set $scope.clicked to false.