Multiple views for one model in AngularJS - model-view-controller

I'm learning AngularJS framework and my background is BackboneJS and it seems I can not figure
out conventional way to do next thing:
I have a readonly list of elements each of which has 'edit' button that switches this
particular element to an edit mode. In edit mode I need to render input elements instead
of spans, p's etc.
The way to do this in Backbone.js is simply create EditView and pass model to it, but I don't have any idea how this works in Angular.
I pass data to the scope and render the readonly list and when user clicks on 'edit' button
in the element how should I change view for the element?
Thanks!

Angular makes this task simpler than Backbone by using a model for editing, then you update the original list and clear the edit model.
The view:
<div ng-app='App'>
<div ng-controller='mainCtrl'>
<div ng-controller='childCtrl'>
<strong>Controller</strong>
<ul>
<li ng-repeat='item in list'>{{item.name}} <button ng-click='edit($index)'>+</button></li>
</ul>
<div ng-show='editModel.name'>
Name: <input type="text" ng-model='editModel.name'/> <button ng-click='save()'>Save</button><button ng-click='cancelEdit()'>Cancel</button>
</div>
</div>
</div>
The angular app:
angular.module('App', [])
.controller('mainCtrl', ['$scope', function($scope){
$scope.list = [ {name:'item 1'}, {name:'item 2'}, {name:'item 3'} ];
}])
.controller('childCtrl', ['$scope', function($scope){
$scope.editModel = {};
$scope.edit = function(index){
$scope.editModel.index = index;
$scope.editModel.name = $scope.list[index].name;
};
$scope.cancelEdit = function(){
$scope.editModel = {};
};
$scope.save = function(){
if($scope.editModel.hasOwnProperty('index')){
$scope.list[$scope.editModel.index] = $scope.editModel;
}
else if($scope.editModel.name && $scope.editModel.name.length){
$scope.list.push($scope.editModel);
}
$scope.cancelEdit();
};
}]);
JsFiddle: http://jsfiddle.net/guilhermenagatomo/Bp6bY/
I'm using the controller nesting so the list can be used by other controllers you have in the app, or maybe you can create a controller just to take care of the editing.

Related

Partial view in NET 6

i am lost with NET6.
I created this partial view _MenuNav.cshtml :
#model IEnumerable<CateringMilano.Models.Menu>
#foreach (var item in Model)
{
<div>
<a alt="#item.MenuTitle)">#item.MenuName</a>
<b>#item.MenuTitle</b>
</div>
}
and the cod in my controller is :
// GET: /Menus/_MenuNav/
public ActionResult _MenuNav(string menuPosition)
{
// Get my db
var model = _context.Menu.Include(m => m.ChildMenuSub) as IQueryable<Menu>;
model = model.Where(p => p.MenuPosition == menuPosition);
// Send your collection of Mreations to the View
return PartialView(model);
}
and in the last project with net 4 i use to write the following code in the principal view in order to call my partial view :
#Html.Action("_MenuNav", "Menus", new { menuPosition = "Menu" })
but it looks like it does not work anymore this with NET6
Do you know how to rewrite my code in order to get the same result?
you must be mixing view components with partial views. Partial view were always used like this
<div id="partialName">
<partial name="_PartialName" />
</div>
with model
<partial name="_PartialName" model="Model.MyInfo" />
or for async
<div id="partialName">
#await Html.PartialAsync("_PartialName")
</div>
and the most popular way to update parital view is using ajax
And you can check my answer about viewcomponents here
https://stackoverflow.com/a/69698058/11392290

Validation of dynamic created form (AngularJS)

I try to made nested form with validation. All works fine, but when I remove one of nested form, validation continue to use removed form. I made jsfiddle example http://jsfiddle.net/sokolov_stas/VAyXu/
When example runs, form are valid. If click "+" button, nested form will be added and valid will be false. Then click "-" button, and valid will be false all the same.
The question is: How to remove dynamic created form from validation processing.
Well, for one thing, a <form> inside of a <form> is not valid HTML.
Second, you're not supposed to be doing DOM manipulation from inside the controller. The controller is for "business" logic. See the section on controllers here
For what you're doing, you'd probably be better off using one form, with an ng-repeat inside of it, and adding additional elements to an array:
<form name="myForm" ng-controller="FormCtrl" ng-submit="doSomething()">
<div ng-repeat="item in items">
<input ng-model="item" type="text" required/>
</div>
<a ng-click="addItem()">+</a>
<a ng-click="removeItem()">-</a>
<button type="submit">Submit</button>
<div>Form valid: {{myForm.$valid}}</div>
</form>
and the controller:
function FormCtrl($scope) {
$scope.items = [];
$scope.addItem = function() {
$scope.items.push(null);
};
$scope.removeItem = function() {
$scope.items.pop();
};
$scope.doSomething = function () {
//your submission stuff goes here.
};
}

Load partial view depending on dropdown selection in MVC3

Im trying to create a from using asp.net mvc3.
I have a dropdownlist with some options.
What i want is different partial views to be injected into the page, depending on the selection in the dropdown list.
But. i dont want this to rely on a submit action. It should function so that, the partial view is loaded as soon as you select from the select list.
I have this code:
#using (Ajax.BeginForm("Create_AddEntity", new AjaxOptions {
UpdateTargetId = "entity_attributes",
InsertionMode = InsertionMode.Replace
}
))
{
<div class="editor-label">
#Html.Label("Type")
</div>
<div class="editor-field">
#Html.DropDownList("EntityTypeList", (SelectList)ViewData["Types"])
</div>
<div id="entity_attributes"></div>
<p>
<input type="submit" value="Create" />
</p>
}
But I can't figure out how to trigger this partial view load when the dropdown list selection changes.
This point is that the form is different for the different "entity types". so there will be loaded a different partial view, depending on the dropdown selection.
Anyone got any pointers?
Let's say following is your view that you want to insert your partial.
<html>
<head><head>
<body>
<!-- Some stuff here. Dropdown and so on-->
....
<!-- Place where you will insert your partial -->
<div id="partialPlaceHolder" style="display:none;"> </div>
</body>
</html>
On the change event of your dropdownlist, get partial via jquery ajax call and load it to place holder.
/* This is change event for your dropdownlist */
$('#myDropDown').change( function() {
/* Get the selected value of dropdownlist */
var selectedID = $(this).val();
/* Request the partial view with .get request. */
$.get('/Controller/MyAction/' + selectedID , function(data) {
/* data is the pure html returned from action method, load it to your page */
$('#partialPlaceHolder').html(data);
/* little fade in effect */
$('#partialPlaceHolder').fadeIn('fast');
});
});
And in your controller action which is /Controller/MyActionin above jquery, return your partial view.
//
// GET: /Controller/MyAction/{id}
public ActionResult MyAction(int id)
{
var partialViewModel = new PartialViewModel();
// TODO: Populate the model (viewmodel) here using the id
return PartialView("_MyPartial", partialViewModel );
}
add the following code to the header of the project (layout).
Add "combobox" to any combo box (select box) which you want to trigger the form that is surrounding it.
$(document).ready(function () {
$('.formcombo').change(function () {
/* submit the parent form */
$(this).parents("form").submit();
});
});

MVC & JQuery Multiple Views Multiple JqueryUI Elements

just a quick question about the mvc JqueryUI framework,
i have a _layout.cshtml page which initializes a set of tabs
i have a view which has a jqueryUI datepicker on it.
the View is loaded Dynamically into the tabs and displayed, but if i load a subsequent instance of the View on the Tabs then the datepicker will only populate the first instance of the datepicker.
my question is this
1. MVC uses independent Objects to create independent Views with the same ids as on the views
2. JQueryUI uses the XML Dom with Unique Ids to create its base objects
so how are these supposed to work together.
my View is as follows
<div class="PoCreate">
<div id="pnlProject">
<fieldset>
<legend>Project</legend>
<label for="ProjectNo">
Project #:
</label>
<input type="text" name="ProjectNo" id="ProjectNo" />
<input type="button" name="btnProjectNo" id="btnProjectNo" data-linked-search="#Url.Action("Project", "SearchObj")"
value=".." />
</fieldset>
</div>
</div>
#Url.Script("~/scripts/PageScripts/_PoIndex.js")
The Script file contains
$('.PoCreate').PoCreate({});
and the PO function contains
$.fn.extend({
PoCreate: function (opt)
{
$(this).each(function ()
{
var _self = $(this.parentNode),
_opts = {}, tabIdContext = $(this.parentNode).attr('id');
$.extend(_opts, (opt || {}));
$('.date', _self).each(function ()
{
$(this).attr('id', tabIdContext + '-' + $(this).attr('id'));
$(this).datepicker(Globals.Dates).keypress(function (e) { return false; });
})
$(':button').button().filter('[data-linked-search]').click(function (e)
{
$.extendedAjax({ url: $(this).attr('data-linked-search'),
success: function (response)
{
$('#dialog-form').find('#dialog-search').html(response).dialog(Globals.Dialogs);
}
});
});
});
}
});
I found a way to solve this,
On the Create of the JQuery Widget i have to rename the ID of the DatePicker field so that it is unique for the Tab created.
so my TabId = ui-tab-01
and DatePickerId = DatePicker1
renaming the DatePickerId so that it is now ui-tab-01-DatePicker1

MVC 3: Why is jquery form.serialize not picking up all the controls in my form?

I am trying to create a situation where if a user clicks on an "edit" button in a list of text items, she can edit that item. I am trying to make the "edit" button post back using ajax.
Here's my ajax code:
$(function () {
// post back edit request
$('input[name^="editItem"]').live("click", (function () {
var id = $(this).attr('id');
var sections = id.split('_');
if (sections.length == 2) {
var itemID = sections[1];
var divID = "message_" + itemID;
var form = $("#newsForm");
$.post(
form.attr("action"),
form.serialize(),
function (data) {
$("#" + divID).html(data);
}
);
}
return false;
}));
});
But the form.serialize() command is not picking up all the form controls in the form. It's ONLY picking up a hidden form field that appears for each item in the list.
Here's the code in the view, inside a loop that displays all the items:
**** this is the only control being picked up: ******
#Html.Hidden(indexItemID, j.ToString())
****
<div class="datetext" style="float: right; margin-bottom: 5px;">
#Model.newsItems[j].datePosted.Value.ToLongDateString()
</div>
#if (Model.newsItems[j].showEdit)
{
// *********** show the editor ************
<div id="#divID">
#Html.EditorFor(model => model.newsItems[j])
</div>
}
else
{
// *********** show the normal display, plus the following edit/delete buttons ***********
if (Model.newsItems[j].canEdit)
{
string editID = "editItem_" + Model.newsItems[j].itemID.ToString();
string deleteID = "deleteItem_" + Model.newsItems[j].itemID.ToString();
<div class="buttonblock">
<div style="float: right">
<input id="#editID" name="#editID" type="submit" class="smallsubmittext cancel" title="edit this item" value="Edit" />
</div>
<div style="float: right">
<input id="#deleteID" name="#deleteID" type="submit" class="smallsubmittext cancel" title="delete this item" value="Delete" />
</div>
</div>
<div class="clear"></div>
}
It's not picking up anything but the series of hidden form fields (indexItemID). Why would it not be picking up the button controls?
(The ID's of the edit button controls, by the way, are in the form "editItem_x" where x is the ID of the item. Thus the button controls are central to the whole process -- that's how I figure out which item the user wants to edit.)
UPDATE
The answer seems to be in the jquery API itself, http://api.jquery.com/serialize/:
"No submit button value is serialized since the form was not submitted using a button."
I don't know how my action is supposed to know which button was clicked, so I am manually adding the button to the serialized string, and it does seem to work, as inelegant as it seems.
UPDATE 2
I spoke too soon -- the ajax is not working to update my partial view. It's giving me an exception because one of the sections in my layout page is undefined. I give up -- I can't waste any more time on this. No Ajax for this project.
You could try:
var form = $('#newsForm *'); // note the '*'
Update
Did you change the argument to $.post() as well? I think I may have been a little too simple in my answer. Just change the second argument within $.post() while continuing to use form.attr('action')
New post should look like this:
$.post(
form.attr("action"),
$('#newsForm *').serialize(), // this line changed
function (data) {
$("#" + divID).html(data);
}
);

Resources