After changing field value in source the view still displays old value.
Angular engine is using 'strict equality'(===) for change detection?
How to solve this problem (I don't like the solution below)? Thx
SOURCE:
export class TestComponent implements OnInit {
date: Date = new Date();
constructor() {
}
ngOnInit() {
}
change() {
this.date.setHours(11); // not working
//const newDate = new Date();
//newDate.setHours(11);
//this.date = newDate; // working
}
}
Template VIEW:
<div>
<button (click)="change()">
Change
</button>
<h4>
{{date}}
</h4>
</div>
try ng-click…
I think you need to do two way data binding in this scenario...
#BitVer try this, you are changing the Date object but it's not two way binding that's why it's not updated in template view.
But you can change the date variable by reassigning to it again.
change() {
this.date = this.date.setHours(11);
}
Related
I went through many links: How to reload the current route with the angular 2 router, but I did not get working solution for me.
I have the edit screen, through Edit Screen I can add student, when I successfully added student, I should be able to see newly added Student in the same screen. Is there any way if we can do this? I am using Angular 7.
addStudents(): void {
this.student.studentId = this.studentId;
console.log(this.student);
this.studentService.saveStudent(this.student).subscribe(response => {
console.log(response);
this.memberResponse = response;
});
this.ngOnInit();
this.router.navigate(['/student-edit', this.studentList]);
}
If you want to use the same screen then why do you need to change the route? or reload the page?
You can do it by boolean only
Like this
Your ts file
export class myComponent {
isEditMode = true;
addStudents(): void {
this.student.studentId = this.studentId;
this.studentService.saveStudent(this.student).subscribe(response => {
this.memberResponse = response;
isEditMode = false;
});
}
}
Now in Html
<div *ngIf="isEditMode">
// HTML for edit screen
</div>
<div *ngIf="!isEditMode">
// HTML for view students screen
</div>
HTML
<div *ngIf="edit">
// edit student form
</div>
<div *ngIf="!edit">
// show all student table
</div>
TS File
openEditForm() { this.edit = true } // When user want to edit or add student
// Called when user clicks save on Edit Form
onSaveButtonClick() {
// Logic to save or edit student using subscription
}
1 . On successful execution of Saving or editing student call the API to GetAllStudents
On successful execution of GetAllStudents set "this.edit = false"
Im having problem that it seems my model not updated after database change. I have a list that each have button to approve or reject.
using (Html.BeginForm("LeaveProcess", "Admin", FormMethod.Post, new { #class = "form-horizontal" }))
{
<input type="text" name="LvAppId" hidden value="#item.LvAppId">
<li><button type="submit" class="btn btn-link" name="AppVal" value=true data-confirm="are u sure?" >Approve</button></li>
<li><button type="submit" class="btn btn-link" name="AppVal" value=false >Reject</button></li>
}
When i press approve or reject button, the value of that submit button is go to controller
[HttpPost]
public ActionResult LeaveProcess(string LvAppId, bool AppVal)
{
DataChange.UpdateStatusFromAdmin(LvAppId, AppVal);
TempData["AlertMessage"] = "Your Action Has Been Processed";
return RedirectToAction("Index");
}
and update database column to "approved" or "reject".
public static void UpdateStatusFromAdmin( string LvAppId, bool AppVal)
{
if (AppVal == true)
{
db.Database.ExecuteSqlCommand("UPDATE LeaveApps SET Status='Approved' WHERE LvAppId={0}", LvAppId);
}
else
{
db.Database.ExecuteSqlCommand("UPDATE LeaveApps SET Status='Rejected' WHERE LvAppId={0}", LvAppId);
}
}
The database is updated (checked it with ssms), but when i reload the page, the value still not updated and i must restart debugging in visual studio to make it updated, what should i do? Thanks
If you are confident that that the query is correct and you can see changes being made to the backend using ssms but the changes aren't being reflected in your app.. I think that is a good indication that there is a problem with the context.
From your code it looks like you aren't disposing of the context properly.
Wrapping your data access inside a using statement like so:
using(var db = new DatabaseContext())
{
// perform data access here
}
Will automatically dispose of it...
See https://msdn.microsoft.com/en-gb/data/jj729737.aspx
If that doesn't solve your problem I'd then focus on your query
Besides writing your values to the database, you do nothing with them.
Create an object of your model and call your view.
var model = new YourModel
{
LvAppId = lvAppId,
AppVal = appVal
};
return View("Index", model);
Otherwise you have to make a call to the database to get your most recent values
I have a partial view on my mvc page. The view is rendered by default with no data, but will be updated based on a value selection from a combobox in another section of the page. The partial view takes an id as a parameter which it will use to get the data needed to return the model.
The problem that I am having is that on the initial load, the parameter is null since nothing has been selected and I am getting a null value exception.
Is there a way that I can use an if statement in a direct events call to check the selected item and return 0 is that is null?
See me sample code below for clarification.
Thanks
Here are the relevant parts of my main page (index.cshtml) -
x.ComboBox()
.ID("MyCombo")
.DisplayField("Title")
.ValueField("Number")
.TypeAhead(false)
.Width(500)
.PageSize(10)
.HideBaseTrigger(true)
.MinChars(0)
.TriggerAction(TriggerAction.Query)
.DirectEvents(de =>
{
de.Select.Url = Url.Action("MyPartial");
#* Can I use an if statment here to check the selected item's value? *#
de.Select.ExtraParams.Add(new { id = App.MyCombo.getValue() });
})
.ListConfig(Html.X().BoundList()
.LoadingText("Searching...")
.ItemTpl(Html.X().XTemplate()
.Html(#<text>
<div class="search-item">
<h3><span>{Number}</span>{Title}</h3>
{Description}
</div>
</text>)
)
)
........
#Html.Partial("MyPartial", Model.MyPartialVM)
and here is my controller code -
public ActionResult MyPartial(string id)
{
var vm = new MyPartialViewModel
{
Number = id,
Title = "New Title"
};
ViewData.Model = vm;
var pvr = new Ext.Net.MVC.PartialViewResult
{
ViewData = this.ViewData
};
return pvr;
}
This works if I hardcode a parameter value, but not if I try it as it is now. Here is the error I get -
Message=Cannot perform runtime binding on a null reference
So I was thinking that I can do an if in teh DirectEvents piece to check for a null on the combobox selection, I can inject a 0 when necessary and handle that in the controller. Can this be done?
Try if this works:
x.ComboBox()
.ID("MyCombo")
.DisplayField("Title")
.ValueField("Number")
.TypeAhead(false)
.Width(500)
.PageSize(10)
.HideBaseTrigger(true)
.MinChars(0)
.TriggerAction(TriggerAction.Query)
.DirectEvents(de =>
{
de.Select.Url = Url.Action("MyPartial");
de.Select.ExtraParams.Add(new {
Name = "id",
Value ="App.MyCombo.getValue() == null ? '0' : App.MyCombo.getValue()",
Mode = ParameterMode.Raw
});
})
.ListConfig(Html.X().BoundList()
.LoadingText("Searching...")
.ItemTpl(Html.X().XTemplate()
.Html(#<text>
<div class="search-item">
<h3><span>{Number}</span>{Title}</h3>
{Description}
</div>
</text>)
)
)
So if your Controller Action returns a Model with pre-populated values, how do you make KnockoutJS aware of them?
E.g.:
#Html.TextBoxFor(m => m.Title, new { data_bind="value: title"} )
however, on $(document).ready() where I bind knockout.js ViewModel, this value isn't yet populated:
$(document).ready({
var viewModel = {
title: ko.observable($("#Title").val()) // too early for this?!
}
ko.applyBindings(viewModel);
});
How do you make KnockoutJS work with MVC's model binding?
One workaround I found was to set the JavaScript variable in my Razor View, like so:
<script>
var strTitle = '#Model.Title';
</script>
and than use it in the Knockout model binding. That works, but I hate it. What if your form has like hundreds of fields? You don't want as many JavaScript variables in your page.
Am I missing the obvious here?
This seems similar to this question. Normally you would set your view model by converting #Model to JSON in a script:
<script type="text/javascript">
var model = #(new HtmlString(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model)));
</script>
You could also create your own binding handler that will initially load the view model based on control values. This new myvalue handler basically calls the existing value handler, except it updates the view model from the initial control value on init.
ko.bindingHandlers['myvalue'] = {
'init': function (element, valueAccessor, allBindingsAccessor) {
// call existing value init code
ko.bindingHandlers['value'].init(element, valueAccessor, allBindingsAccessor);
// valueUpdateHandler() code
var modelValue = valueAccessor();
var elementValue = ko.selectExtensions.readValue(element);
modelValue(elementValue); // simplified next line, writeValueToProperty isn't exported
//ko.jsonExpressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue, /* checkIfDifferent: */ true);
},
'update': function (element, valueAccessor) {
// call existing value update code
ko.bindingHandlers['value'].update(element, valueAccessor);
}
};
Then when you call ko.applyBindings, your observable will be set based on the control's value initially:
<input type="text" data-bind="myvalue: Title" value="This Title will be used" />
<input type="text" data-bind="value: Title" value="This will not be used" />
<!-- MVC -->
#Html.TextBoxFor(m => m.Title, new { data_bind="myvalue: Title"} )
SAMPLE FIDDLE
What about simply serializing your entire page model to json using JSON.NET or similar. Then your page will be populated via normal razor view bindings for non-js users. Then your page scripts can be something like:
<script>
ko.applyBindings(#Html.ToJSON(Model));
</script>
Or if you have a typed viewModel
<script>
var viewModel = new MyViewModel(#Html.ToJSON(Model));
ko.applyBindings(viewModel);
</script>
It makes sense to structure your client side and actual view models the same so no manipulation of the json shape is required.
EDIT
Example of the toJSON helper.
public static MvcHtmlString ToJson(this HtmlHelper html, object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return MvcHtmlString.Create(serializer.Serialize(obj));
}
Hope this helps.
Because I don't have a 50 point reputation to add a comment to the Jason Goemaat answer, I decided to add my comment here as an answer.
All the credits go to Jason Goemaat.
I wasn't able to make the code work for me. So I had to make a small change.
ko.bindingHandlers['myvalue'] = {
'init': function (element, valueAccessor, allBindingsAccessor) {
//get initial state of the element
var modelValue = valueAccessor();
var elementValue = ko.selectExtensions.readValue(element);
// call existing value init code
ko.bindingHandlers['value'].init(element, valueAccessor, allBindingsAccessor);
//Save initial state
modelValue(elementValue);
},
'update': function (element, valueAccessor) {
// call existing value update code
ko.bindingHandlers['value'].update(element, valueAccessor);
}
};
if I had this line at the top,
// call existing value init code
ko.bindingHandlers['value'].init(element, valueAccessor, allBindingsAccessor);
It was deleting the original state of the element. So whatever value I had in the input field, it was being deleted.
Inside the model I have this:
//publishing comment
self.publishingComment = ko.observable();
And my MVC looks like this
#Html.TextBoxFor(model => model.Comment, new { data_bind = "myvalue: publishingComment" })
I have a webpage with two radiobuttons and a dropdownlist as follows:
<div class="sectionheader">Course
<div class="dropdown"><%=Html.DropDownList("CourseSelection", Model.CourseList, new { #class = "dropdown" })%> </div>
<div class="radiobuttons"><label><%=Html.RadioButton("CourseType", "Advanced", false )%> Advanced </label></div>
<div class="radiobuttons"><label><%=Html.RadioButton("CourseType", "Beginner", true )%> Beginner </label></div>
</div>
The dropdownlist is strongly typed and populated with Model.CourseList (NB - on the first page load, 'Beginner' is the default selection and the dropdown shows the beginner course options accordingly)
What I want to be able to do is to update the DropDownList based on which radiobutton is selected i.e. if 'Advanced' selected then show one list of course options in dropdown, and if 'Beginner' selected then show another list of courses.
Edit - posted my own answer below to show solution that worked for me (finally!)
Continue to return your collection of selectlistitem; this translates to JSOn nicely, at least it should, as an array of objects that look like { text: "a", value: "1" } and you can loop through the array and recreate the list this way...
So it will work with strongly-typed objects. You just have to take the objects and construct the elements for the underlying drop down.
HTH.
The code I would like to call sits within my Controller:
public ActionResult UpdateDropDown(string courseType)
{
IDropDownList dropdownlistRepository = new DropDownListRepository();
IEnumerable<SelectListItem> courseList = dropdownlistRepository.GetCourseList(courseType);
return Json(courseList);
}
Using examples provided in jQuery in Action, I now have the following jQuery code:
$('.radiobuttons input:radio').click(function()
{
var courseType = $(this).val(); //Get selected courseType from radiobutton
var dropdownList = $("#CourseSelection"); //Ref for dropdownlist
$.post("/ByCourse/UpdateDropDown", { courseType: courseType }, function(data) {
$(dropdownList).loadSelect(data);
});
});
The loadSelect function is taken straight from the book and is as follows:
(function($) {
$.fn.emptySelect = function() {
return this.each(function() {
if (this.tagName == 'SELECT') this.options.length = 0;
});
}
$.fn.loadSelect = function(optionsDataArray) {
return this.emptySelect().each(function() {
if (this.tagName == 'SELECT') {
var selectElement = this;
$.each(optionsDataArray, function(index, optionData) {
var option = new Option(optionData.Text, optionData.Value);
if ($.browser.msie) {
selectElement.add(option);
}
else {
selectElement.add(option, null);
}
});
}
});
}
})(jQuery);