Since breeze can not submit to the database without looking out for mapped entity, then there is a need to extend the model to give you freedom to create your own calculated properties. reference: http://www.johnpapa.net/new-breeze-angular-service/
I have an extended model, using John Papa SPA project pattern,
I have created a table that require submitting a computed properties along with the users input, i.e Date/Time/UsersId i think the only way to achive this is creating an extended model check this link - http://prntscr.com/77cipy
The extended model auditId is a field in the database and bindable object,
Now the problem is, if i want to call the record from the database using ngRepeat and bind the field auditid to view using {{m.auditId}} i keep getting the object from the computed property. Now, i create another property called {{m.formattedAuditId}}
Object.defineProperty(Medication.prototype, 'formattedAuditId', {
get: function () {
var fn = this.auditId;
return fn;
}
});
The Other View Page that get auditId from the database.
<table class="table table-striped">
<thead>
<th>Generic Name</th>
</thead>
<tr data-ng-repeat="m in vm.medication">
<td>{{m.formattedAuditId}}</td>
<td><strong>{{m.genericName}}</strong></td>
</tr>
</table>
It is still inheriting from the auditId Property i created.
Please what can i do, to bind value from the database instead of the computed property that i created.
Javascript Code:
function registerMedication(metadataStore) {
metadataStore.registerEntityTypeCtor('Medication', Medication);
function Medication() {
//this.isPartial = false;
}
/// This part is the computed property
Object.defineProperty(Medication.prototype, 'auditId', {
get: function () {
var value = moment().format('llll');
return value;
},
set: function (value) {
return value;
}
});
/// This part is where i want the the value to come from the database
Object.defineProperty(Medication.prototype, 'formattedAuditId', {
get: function () {
var fn = this.auditId;
return fn;
}
});
}
The HTML Part
<form class="contact_form" role="form" id="contact_form">
<fieldset class="left">
<label>Audit Id</label>
<div class="block">
<input data-ng-model="vm.medication.auditId"
placeholder="Patient ID" class="text_input"
type="text" />
</div>
<label>Generic Name</label>
<div class="block">
<input data-ng-model="vm.medication.genericName"
placeholder="Generic Name" class="text_input"
type="text" />
</div>
</fieldset>
</form>
Thanks.
Related
This app allows user to enter the quantity of questions for specific topic inside a workbook. I’m trying to sum up all the questions and give an output of totalQuestions.
I created a function (findTotalQuestions().) that will run when Quantity input box is changed. I’m getting an error in Console: Cannot read property 'quantity' of undefined. I’m thinking its because $scope.skill.quantity is not being passed into function. How can I fix this?
<div class="input-field col m3" ng-model="totalQuestions">
<medium>Total Questions in Workbook: </medium>{{totalQuestions}}
</div>
HTML
<table>
<tr>
<th> Skill </th>
<th> Quantity </th>
</tr>
<tr ng-repeat="skill in newWorkbook.skills">
<td>
{ skill.topicText }}
</td>
<td>
<p>
<input id="quantity{{ skill.TopicId }}" type="number" class="validate" ng-model="skill.quantity" required="true" autocomplete="off" ng-change="findTotalQuestions()">
</p>
</td>
</tr>
</table>
Controller:
$scope.getProposedSkills = function() {
return $http.get("/api/topics?SubjectId=" + $scope.newWorkbook.SubjectId).then(function(skills) {
return $scope.newWorkbookskills = _.map(skills.data, function(skill) {
var obj;
obj = {
TopicId: skill.id,
quantity: 0,
level: null,
topicText: skill.topicText,
startLevel: skill.startLevel,
endLevel: skill.endLevel
};
return obj;
});
});
};
$scope.findTotalQuestions = function() {
$scope.totalQuestions = 0;
$scope.totalQuestions = $scope.totalQuestions + $scope.skill.quantity;
return console.log($scope.totalQuestions);
};
Move your getProposedSkills() code in a service then in the controller set the $scope.skill like below
app.service('service',function($http){
return {getProposedSkills:$http.get('your api url')};
})
Your controller should look like below
app.controller('ctrl',function($scope,$http,service){
$scope.getProposedSkills = service.getProposedSkills().then(function(res){
$scope.skill=res;
})
$scope.findTotalQuestions = function() {
$scope.totalQuestions = 0;
$scope.totalQuestions = $scope.totalQuestions + $scope.skill.quantity;
return console.log($scope.totalQuestions);
}
})
And other question i can't find the place where you set $scope.skill in your controller,
if it's a paremeter to be used in your funcion, you should receive it as a paremter of your function and pass it form the view
if it's a variable on your controller it should be initialized or at least check if it exists.
By the way, In the html you have a div with ng-model, this is not correct ng-model should be place inside form inputs (select, input, textarea)
So, I'm not entirely sure how to phrase this question as it's sort of two in one. I'm having a weird issue where I have an object constructor to create new 'projects' from an HTML form which are then pushed into an observableArray when the form is submitted. Everything works fine but to reference the related observables I have to use 'value: Project.title' or 'value: Project.whatever'. I haven't seen 'value: NameOfConstructor.property' used in any of the examples I've seen. I assume this works this way because the constructor is outside of my view model.
My question is this: Is there a better way to assign the value of a property in a constructor that is not in my view model? In other words, is there a better or more correct way than 'Project.title', ect?
I ask partially because one thing in my code doesn't work currently; the knockout enable property doesn't work on my "New Project" button, it stays disabled even if there is something written in the 'title' input box. I have the feeling it's because it's written as data-bind='enable: Project.title' but I can't figure how else to write it.
I've included a jsfiddle for reference though it obviously isn't working because of external dependencies.
https://jsfiddle.net/bmLh0vf1/1/
My HTML:
<form id='addBox' action='#' method='post'>
<label for='pTitle'> Title: </label>
<input id='pTitle' data-bind='value: Project.title' />
<br/>
<label for='pPriority'> Priority </label>
<select id='pPriority' data-bind='options: priorityOptions, value: Project.priority'></select>
<br/>
<button data-bind='enable: Project.title, click: newProject'>New Project</button>
</form>
And my Javascript:
function Project(title, priority) {
this.title = ko.observable(title);
this.priority = ko.observable(priority);
};
function ProjectViewModel() {
var self = this;
this.priorityOptions = ko.observableArray(['High', 'Medium', 'Low'])
this.projectList = ko.observableArray([
new Project('Create App', 'High')
]);
this.newProject = function() {
var np = new Project(Project.title, Project.priority);
self.projectList.push(new Project(Project.title, Project.priority));
console.log(self.projectList().length);
if (self.projectList().length > 1) {
console.log(self.projectList()[1].title());
};
}
};
var viewModel = new ProjectViewModel();
$(document).ready(function() {
ko.applyBindings(viewModel);
});
Lastly, I apologize if I've missed any posting conventions or if my code is especially bad. I'm very new and still teaching myself.
Your code is setting title and priority properties on the object created by new Project, but then later you're expecting to see those properties on Project itself. It doesn't have them; Project is the function, not the object created by new Project. So Project.title and Project.priority will give you undefined (and not an observable, and so not useful targets for the value binding).
Instead, have an "editing" Project instance that you use, binding the value of the inputs to the editing' instances title and priority, and then in newProject grab that instance and replace it with a new, fresh one.
Roughly speaking, in ProjectViewModel's constructor:
this.editing = ko.observable(new Project());
Update Project to default title and priority:
function Project(title, priority) {
this.title = ko.observable(title || "");
this.priority = ko.observable(priority || "Medium");
}
And in the bindings:
<input id='pTitle' data-bind='value: editing().title' />
<select id='pPriority' data-bind='options: priorityOptions, value: editing().priority'></select>
And in newProject:
var np = this.editing();
this.editing(new Project());
Then use np (instead of another new Project) when adding to the array.
Here's a simplified example:
function Project(title, priority) {
this.title = ko.observable(title || "");
this.priority = ko.observable(priority || "Medium");
}
function ProjectViewModel() {
var self = this;
this.priorityOptions = ko.observableArray(["High", "Medium", "Low"]);
this.projects = ko.observableArray();
this.editing = ko.observable(new Project());
this.addProject = function() {
this.projects.push(this.editing());
this.editing(new Project());
};
}
ko.applyBindings(new ProjectViewModel(), document.body);
<div>
<div>
<label>
Title:
<input type="text" data-bind="value: editing().title, valueUpdate: 'input'">
</label>
</div>
<div>
<label>
Priority:
<select data-bind='options: priorityOptions, value: editing().priority'></select>
</label>
</div>
<div>
<button type="button" data-bind="click: addProject, enable: editing().title">Add Project</button>
</div>
<hr>
<div>Projects:</div>
<div data-bind="foreach: projects">
<div>
<span data-bind="text: title"></span>
(<span data-bind="text: priority"></span>)
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
I am trying to pass value like this from view to controller in angular js of this form. I do not wish to hardcode it in this way. How could it be done in proper manner?
angular.module('user').controller('UsersController', ['$scope', '$stateParams', 'Users',
function($scope, $stateParams, Orders) {
$scope.create = function() {
var user = new Users({
child: [
{ columnA: child[0].columnA, columnB: child[0].columnB, columnC: child[0].columnC },
{ columnB: child[1].columnA, columnB: child[1].columnB, columnC: child[1].columnC },
...
{ columnC: child[10].columnA, columnB: child[10].columnB, columnC: child[10].columnC }
]
});
}
}
});
<form data-ng-submit="create()">
<input type="text" data-ng-model="child[0].columnA">
<input type="text" data-ng-model="child[0].columnB">
<input type="text" data-ng-model="child[0].columnC">
<input type="text" data-ng-model="child[1].columnA">
<input type="text" data-ng-model="child[1].columnB">
<input type="text" data-ng-model="child[1].columnC">
......
<input type="text" data-ng-model="child[10].columnA">
<input type="text" data-ng-model="child[10].columnB">
<input type="text" data-ng-model="child[10].columnC">
</form>
It would be better if an reusable directive that may perform above function.
$scope.create = function() {
child: toJSON(child);
}
function toJSON(var a) {
//automatically search through the view for ng-model with child[index].columnName and change to the form above.
}
I wrote out a plunker that demonstrates one way to do something similar to what you are trying to do using angular practices.
You'll note that I eliminated all the duplication in the view by using ng-repeat, and have made the number of child elements dynamic. I initialized the users object with an empty array, but you could easily initialize the object with data from the server.
Note also that changes to the form are immediately reflected in the object, meaning in the create() function, you can serialize the users object, not the form values. In practice, this is probably not necessary, however, since if you use an angular library like $http, serialization to and from JSON is performed automatically.
$scope.users = {
child: [{}]
};
$scope.create = function() {
var data = angular.toJson($scope.users);
alert(data);
};
$scope.addUser = function() {
$scope.users.child.push({});
};
<form ng-submit="create()">
<div ng-repeat="user in users.child">
<input type="text" ng-model="user.columnA">
<input type="text" ng-model="user.columnB">
<input type="text" ng-model="user.columnC">
</div>
<button type="submit">Submit</button>
</form>
<button ng-click="addUser()">Add New User</button>
<pre> {{users}}</pre>
The main takeaway from this, however, should be that the view and the controller work together to eliminate duplication and unnecessary references. we are no longer referring to child[0] in the HTML, making the HTML more readable and maintainable.
I have a HTML template like this:
<div ng-controller="MyCtrl">
<input ng-model="model.name" /> {{model.addr}}
<button ng-click="detect()">detect</button>
</div>
And this is the controller:
function MyCtrl($scope) {
$scope.detect = function() {
var fields = []; //['model.name', 'model.addr']
//call server with selected fields
}
}
The template can be customized by user and generated dynamically, not static template. I want to optimize the data model returned from server, only return values for needed fields in the template. The idea is I want to get all the ng-model fields from template and pass them to the server. The returned data will contain only values for these fields, instead of whole data model, for example:
{
name: 'Superhero',
addr: 'Mars'
}
If I change the template like this (remove model.addr):
<div ng-controller="MyCtrl">
<input ng-model="model.name" />
<button ng-click="detect()">detect</button>
</div>
The fields array should be ['model.name'] and the returned data from the server should be:
{
name: 'Superhero'
}
There are any ways to get all ng-model fields in the scope?
Thanks!
You can do 1 thing, wherever you are using ng-modal, take an object modal and assign values by using dot(.).
Suppose
<div ng-controller="MyCtrl">
<input ng-model="model.name1" />
<input ng-model="model.name2" />
<input ng-model="model.name3" />
<button ng-click="detect()">detect</button>
So you can get model in scope hence all the attributes of scope.
Here is my situation, I have this HTML:
<input type="text" ng-model="inputModel" />
<div class="button-container">
<button type="button" ng-click="setValue(inputModel)"></button>
</div>
<input type="text" ng-model="inputModelTwo" />
<div class="button-container">
<button type="button" ng-click="setValue(inputModelTwo)"></button>
</div>
And my view controller:
$scope.setValue = function (valueToSet) {
valueToSet = "Some value.";
};
I need to be able to "connect" the input fields and their buttons and I'm doing this by having the respective button pass the respective input field's model to the controller to be modified. The problem is that when I click the button the function fires off and valueToSet is changed but the change isn't reflected back in the view! What am I missing?
If you are trying to dynamically pass in your models as a function parameter, you'll need to access a PROPERTY on the models by using dot notation.
Try defining the models in the controller like so:
$scope.inputModel = {};
$scope.inputModelTwo = {};
$scope.inputModel.text = 'hey';
$scope.inputModelTwo.text = 'ho';
Then pass in the entire model to the function as you were already doing.
Inside the function, alter the property that you desire (in this case 'text'), like so:
$scope.setValue = function (valueToSet) {
console.log(valueToSet);
valueToSet.text = "Some value.";
};
JSFiddle