AngularJS and embedded framework html - javascript

I'm developing a user preferences page and I've decided to use AngularJS to control the state of the data.
What I would like to achieve is a page that shows the current user's settings and allows a user to edit them, cancel their changes, or save & submit changes if they so desire. I've binded my labels and my input controls to the model so that when a user modifies their email address, it is reflected across correctly.
I'm basing my work off this example #3 by the way: http://code.angularjs.org/1.0.0rc12/docs-1.0.0rc12/guide/forms
My question is related to the default values for the page. Since the model is defined as an object in Javascript. In the link above, default values can be set over here in $scope.master= {}; which works fine except that I'm using a framework to generate a static page and not retrieving an json object from my server. My pages are all written in embedded scala, so I access the values serverside. What is the best way to take the info retrieved serverside and turn into an object client side javascript can access?

You have a few choices. The way I would do it would be to push the initial state (through a WebSocket or something) to Angular as JSON, or have Angular pull it from the server through an HTTP call.
You could also perhaps render the page with ng-init tags to set the initial state, but this way seems weird to me.
<div ng-controller="FormController" ng-init="formData = {}">
<form>
<input ng-model="formData.input1" ng-init="formData.input1 = 'initialValue'>
</form>
</div>

I am using ASP.NET and Dapper-Dot-Net. I use the following techniques to get my data on to the page and then into Angular scope. It should be pretty transferable to your environment.
Define a DataTransferObject class in the page on the server side and a public string called DtoJson to hold the serialized version of your class instance.
private class DataTransferObject{
public User User;
public List<Project> Projects
}
public string DtoJson;
var dto=new DataTransferObject();
var userName="however you get a username";
dto.User=User.Get(userName); // I already have a User class
var sql="select * from projects where user_name=:UserName";
var p=new DynamicParameters();
p.Add(":UserId", dto.User.ID);
dto.Projects=Project.Query<Project>(sql, p); // returns a list of Project
// I use json.net to convert the Dto to json and expose it as a public variable
var DtoJson=Json.Convert(dto); // approximate syntax but you get the idea
On the client side I put a script tag at the head of the page and inject the DtoJson into it to get it into the global scope
<script>var dto=<%=DtoJson%>;</script>
At the bottom of my page I have a script src="pageName.js" which is my Angular controller file. Inside the controller I say
$scope.dto=dto;
console.log($scope.dto);
Now the json that was created on the server side is in my controller's scope and I can data bind to {{dto.User.FIRST_NAME}} and {{dto.Projects[0].ID}} ng-repeat="for p in dto.Projects" etc
I hope that that makes sense.
Peter

Related

Mvc use string on multiple page

I'm making a patient web app. When user add new patient, I want to keep this patient information(name, surname, phone etc.) I created a static class for patient info values. I set datas on this class. How can I get this info on another views?
This is info class: https://imgur.com/a/LnncS3S
I tried access on view like that:
#{Dentilog.Models.patientinfo.patient_id}
I getting data on views like that (I already set data values on form input)
https://imgur.com/a/h4JprXO
and in controller: https://imgur.com/a/225dBe6
I dont have any problem for getting data. How can use that data on another page?

Backbone.model.save(): POST(create) / PUT(update) logic doesn't match application logic - how to avoid PUT in certain situations?

I'm creating an Web-Application (Frontend and Backend, so both are under my control) using Backbone and Pyramid, being connected via a RESTful API.
During development I encountered a problem several times by now, where Backbone PUTs (=updates) a new model, while it actually should POST (=create) it.
Backbone decides whether to POST or UPDATE a model depending of the presence of an ID-field (if no ID present in the current model: -> POST/create | if so: PUT/update).
However I encountered several situations by now, where this behaviour doesn't match my application logic.
Let's say our main model (and its objects being persistently saved in a relational database in the backend) is called Foo, having fields like id, field_1, field_2.
Example #1: Creating a template or preview of Foo: Before creating (=POSTing) an object of Foo, I can create and show a preview to the user and/or save it as a template.
While doing so, the backend (in case of the preview: temporarily) adds the object to the database and returns the full model - including an ID in its HTTP response - back to Backbone.
Template- and Preview-objects of Foo are (temporarily) saved into the same table, as final objects (column type indicates its type (0 = final/live, 1 = preview, 2 = template)).
When now - after previewing / saving as template - trying to actually CREATE an object of Foo, the Backbone model already has the ID field set and actually PUTs and updates the template or not-anymore-existing preview, instead of POSTing and therewith creating a new Foo inside the database (as intended).
=> solution #1: calling POST /json/preview does not return the ID field, so Backbone doesn't get confused.
=> solution #2: overriding parse() of Foo in Backbone-model to kick out ID field from response
.=> kinda works
Example #2: Having a Periodic model, which refers to a Foo-template. Intention of a Periodic is to offer the user the possibility of semi-automatically creating a new Foo object based on a Foo-template every X months.
Now there is a call GET /json/periodics, which returns all Periodic-objects with its nested Foo-objects (Foo-templates), including their IDs, e.g. [{'interval': 12, template_id: 42, template: { 'id': 42, field_1: 'foo', field_2: 'bar', .. } , { .. } , .. ].
On the frontend the user now can periodically confirm (or skip) creating a new Foo-object, by issuing: periodics[X].template.save() which however again PUTs and therewith updates the Foo-model, instead of POSTing and creating a new one (as intended).
Here again (as in example 1), I could strip out the ID field of Foo - either in the backend or frontend.
However there are situations, where I need the id-field of templates, e.g. when actually editing them, so here I'd need two calls (GET /json/templates_WITHOUT_FOO-IDs and GET /json/templates_WITH_FOO-IDs). which also sounds far from right.
Question is: What's the right (and consistent) way of avoiding Backbone falsely assuming a model should be PUT instead of POSTed in certain situations / views?
Backbone's save and fetch methods just make calls to the Backbone.sync
method, which in turn is just a wrapper for an ajax call. you can pass
in ajax parameters using the save function without having to actually
extend it. basically ends up being something like this:
model.save({attributes you want to save}, {type:'POST', url: 'apiurl/model/:id/played'});
You would have to do this every time though so it is probably better practice to extend Backbone.sync for your model.
The Backbone website has a bit of information about what I'm talking about as far as the Backbone sync and save taking ajax options. There are also a few examples I've seen on extending sync but I can't seem to track them down at the moment.

angular variable initialization

I have a variable in angular controller, $scope.abc.
I have Sails as backend.
$scope.abc's initial value can be determined by backend when generating the page. After the page is displayed to user, $scope.abc may or may not be changed by the user.
I can have backend to generate a complete static page and let angular query the backend for initial value of $scope.abc. I feel it is not necessary as the initial value can be determined at the page's generation and should come as part of the page.
The question is: how to initialize $scope.abc when the webpage is being generated? Is there any way to provide data to angular js file, similar to res.view("",data)?
You don't really have many options here. You can issue one more ajax request and load data. However it my be not ideal if during index page loading the data is already available. In this case you can inject it into additional script tag and access it from from there.
<script>
// Make sure data is JSON encoded.
window.appConfig = <%= data %>;
</script>
<script src="angular.js"></script>
<script src="app.js"></script>
And then I would set a constant service in the app to store data in it:
angular.module('app').constant('appConfig', {data: window.appConfig});
This way you could use it later in more Angular way, for example:
angular.module('app').controller(function($scope, appConfig) {
$scope.config = appConfig.data.userId;
});
And if you are concerned with presence of the global variable appConfig, you can remove it in app run block, when constant is already set.

Auto refresh label in MVC View

I have an auto refresh method (something like below) in my controller. In which I will update data in ViewBag, which I use in label of view. But I'm unable to refresh my label automatically. Please help me.
var waitHandle = new AutoResetEvent(false);
ThreadPool.RegisterWaitForSingleObject(waitHandle,(state, timeout) =>
{
// my viewbag
viewbag.time = DateTime.Now.TimeOfDay;
viewbag=date
}, null, TimeSpan.FromSeconds(5), false);
MVC doesn't work like WebForms (where reassigning a value populates to the UI). You'll need to write a separate action (or WebAPI method) and use AJAX/JavaScript to pull updates. (Alternatively you could use SignalR, but that may be overkill).
Also, if this is a recurring event, you may want to look into a library like Quartz.NET to perform the action. Then, post updates to a shared resource (looks like you're storing timestamp of last execution). From there, use setInterval/AJAX on the client to retrieve and display that value.

Updating/Returning ViewModel Back To Server

Being fairly new to web dev and MVC4, I am encountering the same design issue repeatedly and was hoping someone could tell me what the right/supported/etc.. solution was in the MVC4 world:
Basically, I've drunk the view model koolaid and have view models for every view in my project, most of which are partial subviews dynamically updating on something of a single page application. All proceeds well generating/rendering the view, and then a user updates a number of values on the client side and it's time to update the server.
As an example, let's say it's a simple container view model:
public class Data {
public List<Prop> Props { get; set; }
}
public class Prop {
public string Id { get; set; }
public int Value { get; set; }
}
So let's just say the user is adding new props to the container. How do I get the modified object back to the server?
So far: If it's important that the server be in sync realtime, I can make a call with each addition/update on the server and then either keep things in sync on the client or simply have the server return the updated view. For simple scenarios like that, all is well.
But I find myself often in the case where I want the client to be able to manipulate the object (through the view/js/etc) and I don't really need to update on the server until they are done and submit. What I really want is to be able to pass the object down with the rendered view, interact with it via Javascript, and then pass the object back to the controller when all is done. How do I that? (Apologies it took a while to get to the point!)
Alternatives I've seen:
-- Quick & Dirty (Encode viewmodel properties to JavaScript in Razor): Which sure will put the object in javascript on the client, though it seems hack-ish to just be serializing the whole object into the client side html without any validation, etc. (Though I do realize eventually that's how the object is making it's way down, but it seems like you're bypassing the whole MVC4 object handling/parsing.)
-- Upshot.Js seemed promising with MS support at one time, but it seems that has died: Current status of Upshot.js
-- Breeze.js (http://www.breezejs.com/) seems to be an attempt to take over there, though my concern there is that it's fairly new and not much broad adoption yet.
Ultimately the thing that makes me feel like I'm missing what must be a somewhat obvious alternative is that all the pieces are clearly built into MVC4 already. When you use a form view for example, your fields are databound to the controls, and when the form is submitted, a parallel JSON object is created, sent to the controller, and then parsed into your POCO ViewModel object for you. That's basically the roundtrip I'm looking for (though retaining the full JSON object clientside). What's the "proper" way to handle that?
Knockout is actually exactly what I'm looking for (or another client side MV* framework), I simply didn't know how to use it.
Credit to #Mathletics and a couple of other SO solutions for point me in the right direction, especially: How to use knockout.js with ASP.NET MVC ViewModels?
The key is really to use the ko.mapping library, and Json encode or serialize the model on the server side. In particular, this script block is working well for me in strongly typed partial view:
<script type="text/javascript">
function viewModel() {
// Additional Knockout Here
};
var jsonModel = '#Html.Raw(JsonConvert.SerializeObject(this.Model))';
var mvcModel = ko.mapping.fromJSON(jsonModel);
var myViewModel = new viewModel();
var g = ko.mapping.fromJS(myViewModel, mvcModel);
ko.applyBindings(g);
</script>
And then you're all set up to use Knockout as per normal:
<div class="row">
<div class="span3">
<h3>Bound Value:</h3>
<span data-bind="text: PropertyName"></span>
</div>
</div>
(This requires knockout.js, knockout.mapping.js, and Newtonsoft.Json - though Json.Encode would work equally well.)
Passing the objects back is then easy. Update your object as normal, and when you pass it back to the controller, you already have you Json object ready to go and will be parsed as per normal to be passed back in as a POCO view model on the server side, completing the round trip.
From your description I can understand that you need to pass collection of objects to the controller and then update the collection. Model binding to collection will make things easier for you.
When binding to collection of single fields it becomes easier however when you want to bind to collection of objects then it becomes a little tricky. There are 2 options sequential binding and non- sequential binding.
Sequential binding:
Here is controller action where the form will be posted (HTTP POST action)
public ActionResult UpdateProps(ICollection<Prop> Props) {
return View(Props);
}
form method="post" action="/Home">
<input type="text" name="[0].Id" value="1001" />
<input type="text" name="[0].Value" value="Prop1" />
<input type="text" name="[1].Id" value="" />
<input type="text" name="[1].Value" value="NewProp" />
<input type="submit" />
</form>
When the form will be posted the values will go something like
[0].Id=1001&[0].Value=Prop1&[1].Id=&[1].Value=NewProp
You can see the indexing [0] and [1]. The model binder will rightly group the objects based on the indexing and you will get the expected collection. After the post your action will get 2 objects in ICollection Props. One with ID 1001 and another one which is newly added.
Now you will notice that if you add new prop dynamically then you need to index it properly using script. Or if that is hard for you then instead of indexing the elements you can post them in the above format. You need to parse the elements and post the form using script. The data should be arranged with index. The parsing gives you another advantage that you can post only the required elements i.e newly added or modified instead of posting them all thus saving the payload.
In non Sequential binding instead of series of number sequence the index is unique value like below:
[PropId1001].Id=1001&[PropId1001].Value=Prop1&[PropIdTemp233].Id=""&[PropIdTemp233].Value=NewProp

Categories

Resources