I believe accessing models in this manner is not ideal.
Nevertheless, the question posed was intriguing and the solution provided adds an element of fun to the problem.
The issue arises from the fact that ng-model
necessitates a reference. While JavaScript does pass modifiable copies of objects, it lacks pass-by-reference semantics as explained in this article: JavaScript does not have pass-by-reference semantics, which means simply passing a string to ng-model
won't work.
However, arrays and objects possess this property. Therefore, the workaround involves returning an array with its first element serving as the reference for ng-model
. This approach may seem a bit unconventional as all objects become arrays with only one element.
Alternatively, returning an object for each scenario instead of a single-element array could also resolve the issue.
Solution utilizing embedded objects
The following solution utilizes an embedded object: http://plnkr.co/edit/MuC4LE2YG31RdU6J6FaD?p=preview which offers a more visually appealing implementation.
Therefore, within your controller:
$scope.getModel = function(path) {
var segs = path.split('.');
var root = $scope.data;
while (segs.length > 0) {
var pathStep = segs.shift();
if (typeof root[pathStep] === 'undefined') {
root[pathStep] = segs.length === 0 ? { value: '' } : {};
}
root = root[pathStep];
}
return root;
}
And in your template:
<p>Hello {{data.person.name.value}}!</p>
<p>Address: {{data.address.value}}</p>
<input ng-model="getModel('person.name').value" />
<input ng-model="getModel('address').value" />
Solution using single-element array
Here is a concise (albeit somewhat unconventional) solution that I managed to devise: http://plnkr.co/edit/W92cHU6SQobot8xuElcG?p=preview
Thus, in your controller:
$scope.getModel = function(path) {
var segs = path.split('.');
var root = $scope.data;
while (segs.length > 0) {
var pathStep = segs.shift();
if (typeof root[pathStep] === 'undefined') {
root[pathStep] = segs.length === 0 ? [ '' ] : {};
}
root = root[pathStep];
}
return root;
}
And in your template:
<p>Hello {{data.person.name[0]}}!</p>
<p>Address: {{data.address[0]}}</p>
<input ng-model="getModel('person.name')[0]" />
<input ng-model="getModel('address')[0]" />