Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

I'm pulling JSON data from a server. Inside the JSON object I'm returning, I have strings that I want to be able to use placeholders with to dynamically insert values entered by the user in the UI.

My understanding is that this is what $compile is for, but I can't seem to get that to work. I'm not sure if this is possible or if I'm just approaching it the wrong way.

Edit: Not sure if I'm explaining well. Got a little further and I updated the Plunk and the code below

A simplified example (view Plunk):

View:

<body ng-controller="MainCtrl">
    <input ng-model="name" type="text" />
    <p ng-bind-html="myval">{{myval}}</p>
    <p>{{name}}</p>
  </body>

Angular App:

var app = angular.module('plunker', ['ngSanitize']);

app.controller('MainCtrl', function($scope, $compile, dataSvc) {
  init();

  function init() {
    $scope.data = dataSvc.getData();
    $scope.name = '';
  }

  $scope.$watch('name', function(newVal, oldVal) {
    var c = $compile('<span>' + $scope.data.vals[0].text + '</span>')($scope);
    console.log(c);
    console.log(c[0]);
    $scope.myval = c[0];
  });
});

app.service('dataSvc', function () {
  this.getData = function () {
    return {
      vals: [
        {
          text: "Hello {{name}}"
        }
      ]
    }
  };
});

This almost works with $compile and the console logs the changes the way I want them to happen, I just can't get it to output on the display.

share|improve this question
    
This feels like an XY problem. Angular doesn't actually have a service to perform this kind of interpolation, because by the time this string is rendered in the browser, the $digest cycle is already complete. you could use a directive and inject the element by hand, but really, there are few reasons that you would store client side expressions in their raw state in the database in the first place. – Claies Aug 7 '15 at 19:16
    
@Claies There is a reason for it and $compile is working, I'm just missing something in it's use. See updates above. – Chris Searles Aug 7 '15 at 19:53
    
compile doesn't work that way; compile creates an element that needs to be added to the elements collection on the page by hand. aside from that, I still contend that the server has no business at all transmitting client side code. – Claies Aug 7 '15 at 20:01
    
@Claies Any suggestions on an alternative? – Chris Searles Aug 7 '15 at 20:07
up vote 3 down vote accepted

I'd suggest you to use $interpolate service while assigning variable to other, which will take care of evaluation of curly braces.

Code

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $interpolate) {
  $scope.test = "Hello {{name}}!";
  $scope.name = 'World';

  init();
  function init() {
    $scope.concat = $interpolate($scope.test)($scope);
  }
});

Working Plunkr

share|improve this answer
    
Thank you! Exactly what I was looking for. – Chris Searles Aug 7 '15 at 20:32

Why don't you write something like this :

$scope.greetingText = "Hello";
$scope.greetingName = "World";

and then

$scope.completeGreeting = $scope.greetingText + $scope.greetingName + "!";

and now in view something like this :

{{greetingText}} {{greetingName}}!

{{completeGreeting}}

share|improve this answer
    
See comment on @Rorschach120's answer. – Chris Searles Aug 7 '15 at 19:01
    
why don't you then use regex to search for {{}} in the string and replace the enclosed string part with veriable values?? – binariedMe Aug 7 '15 at 19:04
    
Most probably overriging string concatenation method will be handy – binariedMe Aug 7 '15 at 19:04
    
The JSON object is being built dynamically on the server so there's no guarantee what string I'm looking for. – Chris Searles Aug 7 '15 at 19:06

Unless you are using ECMA6, brackets({{}}) are reserved for interpolating strings in HTML, not javascript.

To achieve what you want in javascript just add the variable to the string:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  $scope.test = "Hello " + $scope.name + "!";

  init();
  function init() {
    $scope.concat = $scope.test;
  }
});

IF you want the JSON to update the name asynchronously or any time after compilation then using a scope variable in the view is exactly what you should do:

<body ng-controller="MainCtrl">
  <p>Hello {{name}}!</p>
</body>

And then in your controller:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';

  function updateName(name) { // call this when the data is ready
    $scope.name = name;
  }
});
share|improve this answer
    
Like I said in my question, the strings are part of a JSON object that's being pulled from the server so this doesn't work. – Chris Searles Aug 7 '15 at 19:01
    
check my edit. You can assign that JSON value to the name. Angular will update the scope and the view will change as soon as the data is ready and you call that function with jsonObj.path.to.name as the callback. – Rorschach120 Aug 7 '15 at 19:05
    
If you post the code for loading the JSON I can show you more specifically. – Rorschach120 Aug 7 '15 at 19:05
    
Doesn't work, the string is being pulled entirely from the server, the view and the controller need to work without knowing what's contained in the string. – Chris Searles Aug 7 '15 at 19:09
1  
So you don't have a reference to the string? You aren't storing it anywhere? Whatever it's value is you still need to be able to access that data through variable. – Rorschach120 Aug 7 '15 at 19:11

I edited your Plnkr, with an input box combined with ngModel. It will output any string you enter in the inputmodel. As I understand you want to output strings which are entered by a user in a UI, so this might work for you.

  <body ng-controller="MainCtrl">
    Name: <input ng-model="userInput" placeholder="Enter your input..."/><br>
    <p>{{userInput || "User input will come here..."}}</p>
  </body>

Plunker

share|improve this answer
    
No, not that simple. See my edit. – Chris Searles Aug 7 '15 at 19:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.